mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 04:07:31 +00:00
feat(idp): provide auto only options (#8420)
# Which Problems Are Solved As of now, **automatic creation** and **automatic linking options** were only considered if the corresponding **allowed option** (account creation / linking allowed) was enabled. With this PR, this is no longer needed and allows administrators to address cases, where only an **automatic creation** is allowed, but users themselves should not be allowed to **manually** create new accounts using an identity provider or edit the information during the process. Also, allowing users to only link to the proposed existing account is now possible with an enabled **automatic linking option**, while disabling **account linking allowed**. # How the Problems Are Solved - Check for **automatic** options without the corresponding **allowed** option. - added technical advisory to notify about the possible behavior change # Additional Changes - display the error message on the IdP linking step in the login UI (in case there is one) - display an error in case no option is possible - exchanged deprecated `eventstoreExpect` with `expectEventstore` in touched test files # Additional Context closes https://github.com/zitadel/zitadel/issues/7393 --------- Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
This commit is contained in:
@@ -533,9 +533,10 @@ func (l *Login) externalUserNotExisting(w http.ResponseWriter, r *http.Request,
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
// if auto creation is disabled, send the user to the notFoundOption
|
||||
// where they can either link or create an account (based on the available options)
|
||||
if !provider.IsAutoCreation {
|
||||
l.renderExternalNotFoundOption(w, r, authReq, orgIAMPolicy, human, idpLink, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -614,6 +615,10 @@ func (l *Login) renderExternalNotFoundOption(w http.ResponseWriter, r *http.Requ
|
||||
l.renderError(w, r, authReq, err)
|
||||
return
|
||||
}
|
||||
if !idpTemplate.IsCreationAllowed && !idpTemplate.IsLinkingAllowed {
|
||||
l.renderError(w, r, authReq, zerrors.ThrowPreconditionFailed(nil, "LOGIN-3kl44", "Errors.User.ExternalIDP.NoOptionAllowed"))
|
||||
return
|
||||
}
|
||||
|
||||
translator := l.getTranslator(r.Context(), authReq)
|
||||
data := externalNotFoundOptionData{
|
||||
|
@@ -19,6 +19,9 @@ func (l *Login) linkUsers(w http.ResponseWriter, r *http.Request, authReq *domai
|
||||
|
||||
func (l *Login) renderLinkUsersDone(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, err error) {
|
||||
var errType, errMessage string
|
||||
if err != nil {
|
||||
errType, errMessage = l.getErrorMessage(r, err)
|
||||
}
|
||||
translator := l.getTranslator(r.Context(), authReq)
|
||||
data := l.getUserData(r, authReq, translator, "LinkingUsersDone.Title", "LinkingUsersDone.Description", errType, errMessage)
|
||||
l.renderer.RenderTemplate(w, r, translator, l.renderer.Templates[tmplLinkUsersDone], data, nil)
|
||||
|
@@ -475,6 +475,7 @@ Errors:
|
||||
NoExternalUserData: Не са получени външни потребителски данни
|
||||
CreationNotAllowed: Създаването на нов потребител не е разрешено на този доставчик
|
||||
LinkingNotAllowed: Свързването на потребител не е разрешено на този доставчик
|
||||
NoOptionAllowed: Нито създаване, нито свързване е разрешено за този доставчик. Моля, свържете се с администратора.
|
||||
GrantRequired: 'Влизането не е възможно. '
|
||||
ProjectRequired: 'Влизането не е възможно. '
|
||||
IdentityProvider:
|
||||
|
@@ -486,6 +486,7 @@ Errors:
|
||||
NoExternalUserData: Nebyla přijata žádná externí uživatelská data
|
||||
CreationNotAllowed: Vytvoření nového uživatele není na tomto poskytovateli povoleno
|
||||
LinkingNotAllowed: Propojení uživatele není na tomto poskytovateli povoleno
|
||||
NoOptionAllowed: Ani vytvoření, ani propojení není povoleno pro tohoto poskytovatele. Obraťte se na svého správce.
|
||||
GrantRequired: Přihlášení není možné. Uživatel musí mít alespoň jeden oprávnění na aplikaci. Prosím, kontaktujte svého správce.
|
||||
ProjectRequired: Přihlášení není možné. Organizace uživatele musí být přidělena k projektu. Prosím, kontaktujte svého správce.
|
||||
IdentityProvider:
|
||||
|
@@ -485,6 +485,7 @@ Errors:
|
||||
NoExternalUserData: Keine externen User-Daten erhalten
|
||||
CreationNotAllowed: Erstellen eines neuen Benutzers mit diesem Provider ist nicht erlaubt
|
||||
LinkingNotAllowed: Verknüpfen eines Benutzers mit diesem Provider ist nicht erlaubt
|
||||
NoOptionAllowed: Weder Erstellung noch Verknüpfung ist für diesen Provider erlaubt. Bitte wenden Sie sich an Ihren Administrator.
|
||||
GrantRequired: Die Anmeldung an diese Applikation ist nicht möglich. Der Benutzer benötigt mindestens eine Berechtigung an der Applikation. Bitte wende dich an deinen Administrator.
|
||||
ProjectRequired: Die Anmeldung an dieser Applikation ist nicht möglich. Die Organisation des Benutzer benötigt Berechtigung auf das Projekt. Bitte wende dich an deinen Administrator.
|
||||
IdentityProvider:
|
||||
|
@@ -484,8 +484,9 @@ Errors:
|
||||
ExternalUserIDEmpty: External User ID is empty
|
||||
UserDisplayNameEmpty: User Display Name is empty
|
||||
NoExternalUserData: No external User Data received
|
||||
CreationNotAllowed: Creation of a new user is not allowed on this Provider
|
||||
LinkingNotAllowed: Linking of a user is not allowed on this Provider
|
||||
CreationNotAllowed: Creation of a new user is not allowed on this provider
|
||||
LinkingNotAllowed: Linking of a user is not allowed on this provider
|
||||
NoOptionAllowed: Neither creation of linking is allowed on this provider. Please contact your administrator.
|
||||
GrantRequired: Login not possible. The user is required to have at least one grant on the application. Please contact your administrator.
|
||||
ProjectRequired: Login not possible. The organization of the user must be granted to the project. Please contact your administrator.
|
||||
IdentityProvider:
|
||||
|
@@ -469,6 +469,7 @@ Errors:
|
||||
NoExternalUserData: No se recibieron datos del usuario externo
|
||||
CreationNotAllowed: La creación de un nuevo usuario no está permitida para este proveedor
|
||||
LinkingNotAllowed: La vinculación de un usuario no está permitida para este proveedor
|
||||
NoOptionAllowed: Ni la creación ni la vinculación están permitidas en este proveedor. Póngase en contacto con su administrador.
|
||||
GrantRequired: El inicio de sesión no es posible. Se requiere que el usuario tenga al menos una concesión sobre la aplicación. Por favor contacta con tu administrador.
|
||||
ProjectRequired: El inicio de sesión no es posible. La organización del usuario debe tener el acceso concedido para el proyecto. Por favor contacta con tu administrador.
|
||||
IdentityProvider:
|
||||
|
@@ -487,6 +487,7 @@ Errors:
|
||||
NoExternalUserData: Aucune donnée d'utilisateur externe reçue
|
||||
CreationNotAllowed: La création d'un nouvel utilisateur n'est pas autorisée sur ce fournisseur.
|
||||
LinkingNotAllowed: La création d'un lien vers un utilisateur n'est pas autorisée pour ce fournisseur.
|
||||
NoOptionAllowed: Ni la création ni la liaison sont autorisées pour ce fournisseur. Veuillez contacter votre administrateur.
|
||||
GrantRequired: Connexion impossible. L'utilisateur doit avoir au moins une subvention sur l'application. Veuillez contacter votre administrateur.
|
||||
ProjectRequired: Connexion impossible. L'organisation de l'utilisateur doit être accordée au projet. Veuillez contacter votre administrateur.
|
||||
IdentityProvider:
|
||||
|
@@ -487,6 +487,7 @@ Errors:
|
||||
NoExternalUserData: Nessun dato utente esterno ricevuto
|
||||
CreationNotAllowed: La creazione di un nuovo utente non è consentita su questo provider.
|
||||
LinkingNotAllowed: Il collegamento di un utente non è consentito su questo provider.
|
||||
NoOptionAllowed: Né la creazione né il collegamento sono consentiti per questo provider. Contattare l'amministratore.
|
||||
GrantRequired: Accesso non possibile. L'utente deve avere almeno una sovvenzione sull'applicazione. Contatta il tuo amministratore.
|
||||
ProjectRequired: Accesso non possibile. L'organizzazione dell'utente deve essere concessa al progetto. Contatta il tuo amministratore.
|
||||
IdentityProvider:
|
||||
|
@@ -450,6 +450,7 @@ Errors:
|
||||
NoExternalUserData: 外部ユーザー情報を取得できません
|
||||
CreationNotAllowed: このプロバイダーでは、新しいユーザーの作成は許可されていません
|
||||
LinkingNotAllowed: このプロバイダーでは、ユーザーのリンクが許可されていません
|
||||
NoOptionAllowed: このプロバイダーでは作成もリンクも許可されていません。 管理者にお問い合わせください。
|
||||
GrantRequired: ログインできません。このユーザーは、アプリケーションに少なくとも1つの権限を付与されていることが必要です。管理者にお問い合わせください。
|
||||
ProjectRequired: ログインできません。ユーザーの組織がプロジェクトに権限を付与されている必要があります。管理者にお問い合わせください。
|
||||
IdentityProvider:
|
||||
|
@@ -487,6 +487,7 @@ Errors:
|
||||
NoExternalUserData: Нема преземени податоци за надворешен корисник
|
||||
CreationNotAllowed: Креирањето на нов корисник не е дозволено на овој провајдер
|
||||
LinkingNotAllowed: Поврзувањето на корисник не е дозволено на овој провајдер
|
||||
NoOptionAllowed: NНиту создавање, ниту поврзување е дозволено за овој провајдер. Ве молиме контактирајте го вашиот администратор.
|
||||
GrantRequired: Не е можно најавување. Корисникот мора да има барем едно овластување за апликацијата. Ве молиме контактирајте го вашиот администратор.
|
||||
ProjectRequired: Не е можно најавување. Организацијата на корисникот мора да биде доделена на проектот. Ве молиме контактирајте го вашиот администратор.
|
||||
IdentityProvider:
|
||||
|
@@ -486,6 +486,7 @@ Errors:
|
||||
NoExternalUserData: Geen externe Gebruiker Data ontvangen
|
||||
CreationNotAllowed: Creatie van een nieuwe gebruiker is niet toegestaan op deze Provider
|
||||
LinkingNotAllowed: Koppeling van een gebruiker is niet toegestaan op deze Provider
|
||||
NoOptionAllowed: Noch aanmaak noch koppeling is toegestaan voor deze provider. Neem contact op met uw beheerder.
|
||||
GrantRequired: Inloggen niet mogelijk. De gebruiker moet minimaal één grant hebben op de applicatie. Neem contact op met uw beheerder.
|
||||
ProjectRequired: Inloggen niet mogelijk. De organisatie van de gebruiker moet toegekend zijn aan het project. Neem contact op met uw beheerder.
|
||||
IdentityProvider:
|
||||
|
@@ -487,6 +487,7 @@ Errors:
|
||||
NoExternalUserData: Nie otrzymano danych użytkownika zewnętrznego
|
||||
CreationNotAllowed: Tworzenie nowego użytkownika nie jest dozwolone w tym Providencie
|
||||
LinkingNotAllowed: Linkowanie użytkownika nie jest dozwolone na tym Providencie
|
||||
NoOptionAllowed: Ani tworzenie, ani łączenie nie jest dozwolone dla tego dostawcy. Skontaktuj się z administratorem.
|
||||
GrantRequired: Logowanie nie jest możliwe. Użytkownik musi posiadać przynajmniej jedno uprawnienie w aplikacji. Skontaktuj się z administratorem.
|
||||
ProjectRequired: Logowanie nie jest możliwe. Organizacja użytkownika musi zostać udzielona projektowi. Skontaktuj się z administratorem.
|
||||
IdentityProvider:
|
||||
|
@@ -483,6 +483,7 @@ Errors:
|
||||
NoExternalUserData: Nenhum dado de usuário externo recebido
|
||||
CreationNotAllowed: A criação de um novo usuário não é permitida neste provedor
|
||||
LinkingNotAllowed: A vinculação de um usuário não é permitida neste provedor
|
||||
NoOptionAllowed: Nem criação nem vinculação são permitidas neste fornecedor. Contate o seu administrador.
|
||||
GrantRequired: Login não é possível. O usuário precisa ter pelo menos uma permissão no aplicativo. Entre em contato com o administrador.
|
||||
ProjectRequired: Login não é possível. A organização do usuário precisa ser concedida ao projeto. Entre em contato com o administrador.
|
||||
IdentityProvider:
|
||||
|
@@ -486,6 +486,7 @@ Errors:
|
||||
NoExternalUserData: Данные внешнего пользователя не получены
|
||||
CreationNotAllowed: Создание нового пользователя для данного провайдера не разрешено
|
||||
LinkingNotAllowed: Привязка пользователя с данным провайдером запрещена
|
||||
NoOptionAllowed: Ни создание, ни связывание не разрешены для этого провайдера. Пожалуйста, обратитесь к администратору.
|
||||
GrantRequired: Вход невозможен. Пользователь должен иметь хотя бы один допуск в приложении. Пожалуйста, свяжитесь с вашим администратором.
|
||||
ProjectRequired: Вход невозможен. Организация пользователя должна иметь допуск к проекту. Пожалуйста, свяжитесь с вашим администратором.
|
||||
IdentityProvider:
|
||||
|
@@ -486,6 +486,7 @@ Errors:
|
||||
NoExternalUserData: Det kom ingen användarinformation från det externa kontot
|
||||
CreationNotAllowed: Det är inte tillåtet att skapa nya konton från den här externa leverantören
|
||||
LinkingNotAllowed: Det är inte tillåtet att koppla ihop konton från den här externa leverantören
|
||||
NoOptionAllowed: Varken skapande eller länkande är tillåtet för denna leverantör. Kontakta administratören.
|
||||
GrantRequired: Det går inte att logga in just nu. Användarkontot har inte tillgång till någonting i tjänsten. Ta kontakt med systemansvarig.
|
||||
ProjectRequired: Det går inte att logga in just nu. Användarkontots organisation har inte tillgång till tjänsten. Ta kontakt med systemansvarig.
|
||||
IdentityProvider:
|
||||
|
@@ -486,6 +486,7 @@ Errors:
|
||||
NoExternalUserData: 未收到外部用户数据
|
||||
CreationNotAllowed: 不允许在该供应商上创建新用户
|
||||
LinkingNotAllowed: 在此提供者上不允许链接一个用户
|
||||
NoOptionAllowed: 此提供商不允许创建或链接。请联系您的管理员。
|
||||
GrantRequired: 无法登录,用户需要在应用程序上拥有至少一项授权,请联系您的管理员。
|
||||
ProjectRequired: 无法登录,用户的组织必须授予项目,请联系您的管理员。
|
||||
IdentityProvider:
|
||||
|
@@ -4,7 +4,9 @@
|
||||
<h1>{{t "LinkingUsersDone.Title"}}</h1>
|
||||
{{ template "user-profile" . }}
|
||||
|
||||
{{if not .ErrID}}
|
||||
<p>{{t "LinkingUsersDone.Description"}}</p>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<form action="{{ loginUrl }}" method="POST">
|
||||
@@ -12,6 +14,8 @@
|
||||
|
||||
<input type="hidden" name="authRequestID" value="{{ .AuthReqID }}" />
|
||||
|
||||
{{template "error-message" .}}
|
||||
|
||||
<div class="lgn-actions">
|
||||
<a class="lgn-stroked-button" href="{{ loginUrl }}">
|
||||
{{t "LinkingUsersDone.CancelButtonText"}}
|
||||
|
@@ -1272,7 +1272,7 @@ func TestCommandSide_AddHuman(t *testing.T) {
|
||||
|
||||
func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
idGenerator id.Generator
|
||||
userPasswordHasher *crypto.Hasher
|
||||
}
|
||||
@@ -1299,9 +1299,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "orgid missing, invalid argument error",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
@@ -1327,8 +1325,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "org policy not found, precondition error",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
expectFilter(),
|
||||
),
|
||||
@@ -1357,8 +1354,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "password policy not found, precondition error",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -1397,8 +1393,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "user invalid, invalid argument error",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -1442,8 +1437,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human (with password and initial code), ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -1529,8 +1523,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human email verified password change not required, ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -1610,8 +1603,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human email verified passwordless only, ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -1710,8 +1702,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human email verified passwordless and password change not required, ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -1814,8 +1805,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human (with phone), ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -1916,8 +1906,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human (with verified phone), ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -2012,8 +2001,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human (with undefined preferred language), ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -2098,8 +2086,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human (with unsupported preferred language), ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -2185,8 +2172,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
name: "add human (with idp), ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -2328,11 +2314,153 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human (with idp, creation not allowed), precondition error",
|
||||
name: "add human (with idp, no creation allowed), precondition error",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"idpID",
|
||||
"name",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeUnspecified,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPOIDCConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"clientID",
|
||||
"idpID",
|
||||
"issuer",
|
||||
"authEndpoint",
|
||||
"tokenEndpoint",
|
||||
nil,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewOIDCIDPChangedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
[]idp.OIDCIDPChanges{
|
||||
idp.ChangeOIDCOptions(idp.OptionChanges{
|
||||
IsCreationAllowed: gu.Ptr(false),
|
||||
IsAutoCreation: gu.Ptr(false),
|
||||
}),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"idpID",
|
||||
"name",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeUnspecified,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPOIDCConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"clientID",
|
||||
"idpID",
|
||||
"issuer",
|
||||
"authEndpoint",
|
||||
"tokenEndpoint",
|
||||
nil,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewOIDCIDPChangedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
[]idp.OIDCIDPChanges{
|
||||
idp.ChangeOIDCOptions(idp.OptionChanges{IsCreationAllowed: gu.Ptr(false)}),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIdentityProviderAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"idpID",
|
||||
domain.IdentityProviderTypeOrg,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
userPasswordHasher: mockPasswordHasher("x"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
links: []*domain.UserIDPLink{
|
||||
{
|
||||
IDPConfigID: "idpID",
|
||||
ExternalUserID: "externalID",
|
||||
DisplayName: "name",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
}
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsPreconditionFailed,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human (with idp, manual creation not allowed), ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
@@ -2422,7 +2550,10 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
[]idp.OIDCIDPChanges{
|
||||
idp.ChangeOIDCOptions(idp.OptionChanges{IsCreationAllowed: gu.Ptr(false)}),
|
||||
idp.ChangeOIDCOptions(idp.OptionChanges{
|
||||
IsCreationAllowed: gu.Ptr(false),
|
||||
IsAutoCreation: gu.Ptr(true),
|
||||
}),
|
||||
},
|
||||
)
|
||||
return e
|
||||
@@ -2436,6 +2567,17 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
newAddHumanEvent("", false, true, "", AllowedLanguage),
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"idpID",
|
||||
"name",
|
||||
"externalID",
|
||||
),
|
||||
user.NewHumanEmailVerifiedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
userPasswordHasher: mockPasswordHasher("x"),
|
||||
@@ -2446,8 +2588,9 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
PreferredLanguage: AllowedLanguage,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
@@ -2465,7 +2608,196 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
}
|
||||
},
|
||||
res: res{
|
||||
err: zerrors.IsPreconditionFailed,
|
||||
wantHuman: &domain.Human{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: AllowedLanguage,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
State: domain.UserStateActive,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "add human (with idp, auto creation not allowed), ok",
|
||||
given: func(t *testing.T) (fields, args) {
|
||||
return fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewDomainPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewPasswordComplexityPolicyAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
1,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"idpID",
|
||||
"name",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeUnspecified,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPOIDCConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"clientID",
|
||||
"idpID",
|
||||
"issuer",
|
||||
"authEndpoint",
|
||||
"tokenEndpoint",
|
||||
nil,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewOIDCIDPChangedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
[]idp.OIDCIDPChanges{
|
||||
idp.ChangeOIDCOptions(idp.OptionChanges{IsCreationAllowed: gu.Ptr(false)}),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"idpID",
|
||||
"name",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeUnspecified,
|
||||
false,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPOIDCConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"clientID",
|
||||
"idpID",
|
||||
"issuer",
|
||||
"authEndpoint",
|
||||
"tokenEndpoint",
|
||||
nil,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewOIDCIDPChangedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
[]idp.OIDCIDPChanges{
|
||||
idp.ChangeOIDCOptions(idp.OptionChanges{
|
||||
IsCreationAllowed: gu.Ptr(true),
|
||||
IsAutoCreation: gu.Ptr(false),
|
||||
}),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIdentityProviderAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"idpID",
|
||||
domain.IdentityProviderTypeOrg,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
newAddHumanEvent("", false, true, "", AllowedLanguage),
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"idpID",
|
||||
"name",
|
||||
"externalID",
|
||||
),
|
||||
user.NewHumanEmailVerifiedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate),
|
||||
),
|
||||
),
|
||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "user1"),
|
||||
userPasswordHasher: mockPasswordHasher("x"),
|
||||
},
|
||||
args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
human: &domain.Human{
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
PreferredLanguage: AllowedLanguage,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
},
|
||||
links: []*domain.UserIDPLink{
|
||||
{
|
||||
IDPConfigID: "idpID",
|
||||
ExternalUserID: "externalID",
|
||||
DisplayName: "name",
|
||||
},
|
||||
},
|
||||
secretGenerator: GetMockSecretGenerator(t),
|
||||
}
|
||||
},
|
||||
res: res{
|
||||
wantHuman: &domain.Human{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
Username: "username",
|
||||
Profile: &domain.Profile{
|
||||
FirstName: "firstname",
|
||||
LastName: "lastname",
|
||||
DisplayName: "firstname lastname",
|
||||
PreferredLanguage: AllowedLanguage,
|
||||
},
|
||||
Email: &domain.Email{
|
||||
EmailAddress: "email@test.ch",
|
||||
IsEmailVerified: true,
|
||||
},
|
||||
State: domain.UserStateActive,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -2473,7 +2805,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
f, a := tt.given(t)
|
||||
r := &Commands{
|
||||
eventstore: f.eventstore,
|
||||
eventstore: f.eventstore(t),
|
||||
idGenerator: f.idGenerator,
|
||||
userPasswordHasher: f.userPasswordHasher,
|
||||
}
|
||||
@@ -2494,7 +2826,7 @@ func TestCommandSide_ImportHuman(t *testing.T) {
|
||||
|
||||
func TestCommandSide_HumanMFASkip(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
}
|
||||
type (
|
||||
args struct {
|
||||
@@ -2516,9 +2848,7 @@ func TestCommandSide_HumanMFASkip(t *testing.T) {
|
||||
{
|
||||
name: "userid missing, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -2532,8 +2862,7 @@ func TestCommandSide_HumanMFASkip(t *testing.T) {
|
||||
{
|
||||
name: "user not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
@@ -2549,8 +2878,7 @@ func TestCommandSide_HumanMFASkip(t *testing.T) {
|
||||
{
|
||||
name: "skip mfa init, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(context.Background(),
|
||||
@@ -2589,7 +2917,7 @@ func TestCommandSide_HumanMFASkip(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
err := r.HumanSkipMFAInit(tt.args.ctx, tt.args.userID, tt.args.orgID)
|
||||
if tt.res.err == nil {
|
||||
@@ -2604,7 +2932,7 @@ func TestCommandSide_HumanMFASkip(t *testing.T) {
|
||||
|
||||
func TestCommandSide_HumanSignOut(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
}
|
||||
type (
|
||||
args struct {
|
||||
@@ -2626,9 +2954,7 @@ func TestCommandSide_HumanSignOut(t *testing.T) {
|
||||
{
|
||||
name: "agentid missing, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -2642,9 +2968,7 @@ func TestCommandSide_HumanSignOut(t *testing.T) {
|
||||
{
|
||||
name: "userids missing, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -2658,8 +2982,7 @@ func TestCommandSide_HumanSignOut(t *testing.T) {
|
||||
{
|
||||
name: "user not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
@@ -2673,8 +2996,7 @@ func TestCommandSide_HumanSignOut(t *testing.T) {
|
||||
{
|
||||
name: "human sign out, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(context.Background(),
|
||||
@@ -2713,8 +3035,7 @@ func TestCommandSide_HumanSignOut(t *testing.T) {
|
||||
{
|
||||
name: "human sign out multiple users, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(context.Background(),
|
||||
@@ -2774,7 +3095,7 @@ func TestCommandSide_HumanSignOut(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
err := r.HumansSignOut(tt.args.ctx, tt.args.agentID, tt.args.userIDs)
|
||||
if tt.res.err == nil {
|
||||
|
@@ -86,12 +86,13 @@ func (c *Commands) addUserIDPLink(ctx context.Context, human *eventstore.Aggrega
|
||||
if err != nil {
|
||||
return nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-39nfs", "Errors.IDPConfig.NotExisting")
|
||||
}
|
||||
options := idpWriteModel.GetProviderOptions()
|
||||
// IDP user will either be linked or created on a new user
|
||||
// Therefore we need to either check if linking is allowed or creation:
|
||||
if linkToExistingUser && !idpWriteModel.GetProviderOptions().IsLinkingAllowed {
|
||||
if linkToExistingUser && !options.IsLinkingAllowed && options.AutoLinkingOption == domain.AutoLinkingOptionUnspecified {
|
||||
return nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-Sfee2", "Errors.ExternalIDP.LinkingNotAllowed")
|
||||
}
|
||||
if !linkToExistingUser && !idpWriteModel.GetProviderOptions().IsCreationAllowed {
|
||||
if !linkToExistingUser && !options.IsCreationAllowed && !options.IsAutoCreation {
|
||||
return nil, zerrors.ThrowPreconditionFailed(err, "COMMAND-SJI3g", "Errors.ExternalIDP.CreationNotAllowed")
|
||||
}
|
||||
return user.NewUserIDPLinkAddedEvent(ctx, human, link.IDPConfigID, link.DisplayName, link.ExternalUserID), nil
|
||||
|
@@ -20,7 +20,7 @@ import (
|
||||
|
||||
func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -40,9 +40,7 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
{
|
||||
name: "missing userid, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -62,9 +60,7 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
{
|
||||
name: "no external idps, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -78,8 +74,7 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
{
|
||||
name: "userID doesnt match aggregate id, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(
|
||||
@@ -120,8 +115,7 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
{
|
||||
name: "invalid external idp, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(
|
||||
@@ -162,8 +156,7 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
{
|
||||
name: "config not existing, precondition error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(
|
||||
@@ -203,10 +196,9 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "linking not allowed, precondition error",
|
||||
name: "no linking not allowed, precondition failed",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(
|
||||
@@ -307,11 +299,236 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
err: zerrors.ThrowPreconditionFailed(nil, "COMMAND-Sfee2", "Errors.ExternalIDP.LinkingNotAllowed"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "auto linking not allowed (manual linking allowed), ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(
|
||||
context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"userName",
|
||||
"firstName",
|
||||
"lastName",
|
||||
"nickName",
|
||||
"displayName",
|
||||
language.German,
|
||||
domain.GenderFemale,
|
||||
"email@Address.ch",
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
"name",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeUnspecified,
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPOIDCConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"clientID",
|
||||
"config1",
|
||||
"issuer",
|
||||
"authEndpoint",
|
||||
"tokenEndpoint",
|
||||
nil,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
"name",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeUnspecified,
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPOIDCConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"clientID",
|
||||
"config1",
|
||||
"issuer",
|
||||
"authEndpoint",
|
||||
"tokenEndpoint",
|
||||
nil,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewOIDCIDPChangedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
[]idp.OIDCIDPChanges{
|
||||
idp.ChangeOIDCOptions(idp.OptionChanges{
|
||||
IsLinkingAllowed: gu.Ptr(true),
|
||||
AutoLinkingOption: gu.Ptr(domain.AutoLinkingOptionUnspecified),
|
||||
}),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"config1",
|
||||
"name",
|
||||
"externaluser1",
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
links: []*domain.UserIDPLink{
|
||||
{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
DisplayName: "name",
|
||||
ExternalUserID: "externaluser1",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{},
|
||||
},
|
||||
{
|
||||
name: "manual linking not allowed (auto linking allowed), ok",
|
||||
fields: fields{
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(
|
||||
context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"userName",
|
||||
"firstName",
|
||||
"lastName",
|
||||
"nickName",
|
||||
"displayName",
|
||||
language.German,
|
||||
domain.GenderFemale,
|
||||
"email@Address.ch",
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
"name",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeUnspecified,
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPOIDCConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"clientID",
|
||||
"config1",
|
||||
"issuer",
|
||||
"authEndpoint",
|
||||
"tokenEndpoint",
|
||||
nil,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
),
|
||||
),
|
||||
),
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
org.NewIDPConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
"name",
|
||||
domain.IDPConfigTypeOIDC,
|
||||
domain.IDPConfigStylingTypeUnspecified,
|
||||
true,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
org.NewIDPOIDCConfigAddedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"clientID",
|
||||
"config1",
|
||||
"issuer",
|
||||
"authEndpoint",
|
||||
"tokenEndpoint",
|
||||
nil,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
domain.OIDCMappingFieldUnspecified,
|
||||
),
|
||||
),
|
||||
eventFromEventPusher(
|
||||
func() eventstore.Command {
|
||||
e, _ := org.NewOIDCIDPChangedEvent(context.Background(),
|
||||
&org.NewAggregate("org1").Aggregate,
|
||||
"config1",
|
||||
[]idp.OIDCIDPChanges{
|
||||
idp.ChangeOIDCOptions(idp.OptionChanges{
|
||||
IsLinkingAllowed: gu.Ptr(false),
|
||||
AutoLinkingOption: gu.Ptr(domain.AutoLinkingOptionEmail),
|
||||
}),
|
||||
},
|
||||
)
|
||||
return e
|
||||
}(),
|
||||
),
|
||||
),
|
||||
expectPush(
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
&user.NewAggregate("user1", "org1").Aggregate,
|
||||
"config1",
|
||||
"name",
|
||||
"externaluser1",
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
userID: "user1",
|
||||
resourceOwner: "org1",
|
||||
links: []*domain.UserIDPLink{
|
||||
{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "user1",
|
||||
},
|
||||
IDPConfigID: "config1",
|
||||
DisplayName: "name",
|
||||
ExternalUserID: "externaluser1",
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{},
|
||||
},
|
||||
{
|
||||
name: "add external idp org config, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(
|
||||
@@ -409,8 +626,7 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
{
|
||||
name: "add external idp iam config, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(
|
||||
@@ -509,7 +725,7 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
err := r.BulkAddedUserIDPLinks(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.links)
|
||||
assert.ErrorIs(t, err, tt.res.err)
|
||||
@@ -519,7 +735,7 @@ func TestCommandSide_BulkAddUserIDPLinks(t *testing.T) {
|
||||
|
||||
func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
checkPermission domain.PermissionCheck
|
||||
}
|
||||
type args struct {
|
||||
@@ -539,9 +755,7 @@ func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
{
|
||||
name: "invalid idp, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
},
|
||||
args: args{
|
||||
@@ -561,9 +775,7 @@ func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
{
|
||||
name: "aggregate id missing, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
},
|
||||
args: args{
|
||||
@@ -580,8 +792,7 @@ func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
{
|
||||
name: "user removed, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
@@ -620,8 +831,7 @@ func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
{
|
||||
name: "external idp not existing, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(),
|
||||
),
|
||||
checkPermission: newMockPermissionCheckAllowed(),
|
||||
@@ -643,8 +853,7 @@ func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
{
|
||||
name: "remove external idp, permission error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
@@ -675,8 +884,7 @@ func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
{
|
||||
name: "remove external idp, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
@@ -717,7 +925,7 @@ func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
checkPermission: tt.fields.checkPermission,
|
||||
}
|
||||
got, err := r.RemoveUserIDPLink(tt.args.ctx, tt.args.link)
|
||||
@@ -736,7 +944,7 @@ func TestCommandSide_RemoveUserIDPLink(t *testing.T) {
|
||||
|
||||
func TestCommandSide_ExternalLoginCheck(t *testing.T) {
|
||||
type fields struct {
|
||||
eventstore *eventstore.Eventstore
|
||||
eventstore func(*testing.T) *eventstore.Eventstore
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
@@ -756,9 +964,7 @@ func TestCommandSide_ExternalLoginCheck(t *testing.T) {
|
||||
{
|
||||
name: "userid missing, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
eventstore: expectEventstore(),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
@@ -772,8 +978,7 @@ func TestCommandSide_ExternalLoginCheck(t *testing.T) {
|
||||
{
|
||||
name: "user removed, not found error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewUserIDPLinkAddedEvent(context.Background(),
|
||||
@@ -806,8 +1011,7 @@ func TestCommandSide_ExternalLoginCheck(t *testing.T) {
|
||||
{
|
||||
name: "external login check, ok",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
eventstore: expectEventstore(
|
||||
expectFilter(
|
||||
eventFromEventPusher(
|
||||
user.NewHumanAddedEvent(context.Background(),
|
||||
@@ -852,7 +1056,7 @@ func TestCommandSide_ExternalLoginCheck(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Commands{
|
||||
eventstore: tt.fields.eventstore,
|
||||
eventstore: tt.fields.eventstore(t),
|
||||
}
|
||||
err := r.UserIDPLoginChecked(tt.args.ctx, tt.args.orgID, tt.args.userID, tt.args.authRequest)
|
||||
if tt.res.err == nil {
|
||||
|
Reference in New Issue
Block a user