new pkg structure (#1150)

* fix: split command query side

* fix: split command query side

* fix: members in correct pkg structure

* fix: label policy in correct pkg structure

* fix: structure

* fix: structure of login policy

* fix: identityprovider structure

* fix: org iam policy structure

* fix: password age policy structure

* fix: password complexity policy structure

* fix: password lockout policy structure

* fix: idp structure

* fix: user events structure

* fix: user write model

* fix: profile email changed command

* fix: address changed command

* fix: user states

* fix: user

* fix: org structure and add human

* begin iam setup command side

* setup

* step2

* step2

* fix: add user

* step2

* isvalid

* fix: folder structure v2 business

Co-authored-by: Fabiennne <fabienne.gerschwiler@gmail.com>
This commit is contained in:
Livio Amstutz 2021-01-04 14:52:13 +01:00 committed by GitHub
parent 762941f0ea
commit 21ffe1b0cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
260 changed files with 7917 additions and 6570 deletions

View File

@ -161,8 +161,8 @@ func startSetup(configPaths []string, localDevMode bool) {
ctx := context.Background() ctx := context.Background()
setup, err := setup.StartSetup(conf.Eventstore, conf.SystemDefaults) setup, err := setup.StartSetupV2(conf.Eventstore, conf.SystemDefaults)
logging.Log("SERVE-fD252").OnError(err).Panic("failed to start setup") logging.Log("SERVE-fD252").OnError(err).Panic("failed to start setup")
err = setup.Execute(ctx, conf.SetUp) err = setup.ExecuteV2(ctx, conf.SetUp)
logging.Log("SERVE-djs3R").OnError(err).Panic("failed to execute setup") logging.Log("SERVE-djs3R").OnError(err).Panic("failed to execute setup")
} }

View File

@ -26,53 +26,53 @@ SetUp:
Step1: Step1:
GlobalOrg: 'Global' GlobalOrg: 'Global'
IAMProject: 'Zitadel' IAMProject: 'Zitadel'
DefaultLoginPolicy: # DefaultLoginPolicy:
AllowUsernamePassword: true # AllowUsernamePassword: true
AllowRegister: true # AllowRegister: true
AllowExternalIdp: true # AllowExternalIdp: true
Orgs: # Orgs:
- Name: 'Global' # - Name: 'Global'
Domain: 'global.caos.ch' # Domain: 'global.caos.ch'
Default: true # Default: true
OrgIamPolicy: true # OrgIamPolicy: true
Users: # Users:
- FirstName: 'Global Org' # - FirstName: 'Global Org'
LastName: 'Administrator' # LastName: 'Administrator'
UserName: 'zitadel-global-org-admin@caos.ch' # UserName: 'zitadel-global-org-admin@caos.ch'
Email: 'zitadel-global-org-admin@caos.ch' # Email: 'zitadel-global-org-admin@caos.ch'
Password: 'Password1!' # Password: 'Password1!'
Owners: # Owners:
- 'zitadel-global-org-admin@caos.ch' # - 'zitadel-global-org-admin@caos.ch'
- Name: 'CAOS AG' # - Name: 'CAOS AG'
Domain: 'caos.ch' # Domain: 'caos.ch'
Users: # Users:
- FirstName: 'Zitadel' # - FirstName: 'Zitadel'
LastName: 'Administrator' # LastName: 'Administrator'
UserName: 'zitadel-admin' # UserName: 'zitadel-admin'
Email: 'zitadel-admin@caos.ch' # Email: 'zitadel-admin@caos.ch'
Password: 'Password1!' # Password: 'Password1!'
Owners: # Owners:
- 'zitadel-admin@caos.ch' # - 'zitadel-admin@caos.ch'
Projects: # Projects:
- Name: 'Zitadel' # - Name: 'Zitadel'
OIDCApps: # OIDCApps:
- Name: 'Management-API' # - Name: 'Management-API'
- Name: 'Auth-API' # - Name: 'Auth-API'
- Name: 'Admin-API' # - Name: 'Admin-API'
- Name: 'Zitadel Console' # - Name: 'Zitadel Console'
RedirectUris: # RedirectUris:
- '$ZITADEL_CONSOLE/auth/callback' # - '$ZITADEL_CONSOLE/auth/callback'
PostLogoutRedirectUris: # PostLogoutRedirectUris:
- '$ZITADEL_CONSOLE/signedout' # - '$ZITADEL_CONSOLE/signedout'
ResponseTypes: # ResponseTypes:
- $ZITADEL_CONSOLE_RESPONSE_TYPE # - $ZITADEL_CONSOLE_RESPONSE_TYPE
GrantTypes: # GrantTypes:
- $ZITADEL_CONSOLE_GRANT_TYPE # - $ZITADEL_CONSOLE_GRANT_TYPE
ApplicationType: 'USER_AGENT' # ApplicationType: 'USER_AGENT'
AuthMethodType: 'NONE' # AuthMethodType: 'NONE'
DevMode: $ZITADEL_CONSOLE_DEV_MODE # DevMode: $ZITADEL_CONSOLE_DEV_MODE
Owners: # Owners:
- 'zitadel-admin@caos.ch' # - 'zitadel-admin@caos.ch'
Step2: Step2:
DefaultPasswordComplexityPolicy: DefaultPasswordComplexityPolicy:
MinLength: 8 MinLength: 8

View File

@ -2,6 +2,7 @@ package eventstore
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/v2/query"
"strings" "strings"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
@ -18,7 +19,7 @@ import (
"github.com/caos/zitadel/internal/telemetry/tracing" "github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model" usr_model "github.com/caos/zitadel/internal/user/model"
usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing" usr_es "github.com/caos/zitadel/internal/user/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam" "github.com/caos/zitadel/internal/v2/command"
) )
type IAMRepository struct { type IAMRepository struct {
@ -30,7 +31,8 @@ type IAMRepository struct {
SystemDefaults systemdefaults.SystemDefaults SystemDefaults systemdefaults.SystemDefaults
Roles []string Roles []string
IAMV2 *iam_business.Repository IAMV2Command *command.CommandSide
IAMV2Query *query.QuerySide
} }
func (repo *IAMRepository) IAMMemberByID(ctx context.Context, iamID, userID string) (*iam_model.IAMMemberView, error) { func (repo *IAMRepository) IAMMemberByID(ctx context.Context, iamID, userID string) (*iam_model.IAMMemberView, error) {
@ -43,24 +45,24 @@ func (repo *IAMRepository) IAMMemberByID(ctx context.Context, iamID, userID stri
func (repo *IAMRepository) AddIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) { func (repo *IAMRepository) AddIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
member.AggregateID = repo.SystemDefaults.IamID member.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddMember(ctx, member) return repo.IAMV2Command.AddIAMMember(ctx, member)
} }
return repo.IAMEventstore.AddIAMMember(ctx, member) return repo.IAMEventstore.AddIAMMember(ctx, member)
} }
func (repo *IAMRepository) ChangeIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) { func (repo *IAMRepository) ChangeIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
member.AggregateID = repo.SystemDefaults.IamID member.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangeMember(ctx, member) return repo.IAMV2Command.ChangeIAMMember(ctx, member)
} }
return repo.IAMEventstore.ChangeIAMMember(ctx, member) return repo.IAMEventstore.ChangeIAMMember(ctx, member)
} }
func (repo *IAMRepository) RemoveIAMMember(ctx context.Context, userID string) error { func (repo *IAMRepository) RemoveIAMMember(ctx context.Context, userID string) error {
member := iam_model.NewIAMMember(repo.SystemDefaults.IamID, userID) member := iam_model.NewIAMMember(repo.SystemDefaults.IamID, userID)
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.RemoveMember(ctx, member) return repo.IAMV2Command.RemoveIAMMember(ctx, member)
} }
return repo.IAMEventstore.RemoveIAMMember(ctx, member) return repo.IAMEventstore.RemoveIAMMember(ctx, member)
} }
@ -97,8 +99,8 @@ func (repo *IAMRepository) GetIAMMemberRoles() []string {
} }
func (repo *IAMRepository) IDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error) { func (repo *IAMRepository) IDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error) {
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.IDPConfigByID(ctx, repo.SystemDefaults.IamID, idpConfigID) return repo.IAMV2Query.DefaultIDPConfigByID(ctx, repo.SystemDefaults.IamID, idpConfigID)
} }
idp, err := repo.View.IDPConfigByID(idpConfigID) idp, err := repo.View.IDPConfigByID(idpConfigID)
@ -110,37 +112,37 @@ func (repo *IAMRepository) IDPConfigByID(ctx context.Context, idpConfigID string
func (repo *IAMRepository) AddOIDCIDPConfig(ctx context.Context, idp *iam_model.IDPConfig) (*iam_model.IDPConfig, error) { func (repo *IAMRepository) AddOIDCIDPConfig(ctx context.Context, idp *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
idp.AggregateID = repo.SystemDefaults.IamID idp.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddIDPConfig(ctx, idp) return repo.IAMV2Command.AddDefaultIDPConfig(ctx, idp)
} }
return repo.IAMEventstore.AddIDPConfig(ctx, idp) return repo.IAMEventstore.AddIDPConfig(ctx, idp)
} }
func (repo *IAMRepository) ChangeIDPConfig(ctx context.Context, idp *iam_model.IDPConfig) (*iam_model.IDPConfig, error) { func (repo *IAMRepository) ChangeIDPConfig(ctx context.Context, idp *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
idp.AggregateID = repo.SystemDefaults.IamID idp.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangeIDPConfig(ctx, idp) return repo.IAMV2Command.ChangeDefaultIDPConfig(ctx, idp)
} }
return repo.IAMEventstore.ChangeIDPConfig(ctx, idp) return repo.IAMEventstore.ChangeIDPConfig(ctx, idp)
} }
func (repo *IAMRepository) DeactivateIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) { func (repo *IAMRepository) DeactivateIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.DeactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID) return repo.IAMV2Command.DeactivateDefaultIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
} }
return repo.IAMEventstore.DeactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID) return repo.IAMEventstore.DeactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
} }
func (repo *IAMRepository) ReactivateIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) { func (repo *IAMRepository) ReactivateIDPConfig(ctx context.Context, idpConfigID string) (*iam_model.IDPConfig, error) {
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ReactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID) return repo.IAMV2Command.ReactivateDefaultIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
} }
return repo.IAMEventstore.ReactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID) return repo.IAMEventstore.ReactivateIDPConfig(ctx, repo.SystemDefaults.IamID, idpConfigID)
} }
func (repo *IAMRepository) RemoveIDPConfig(ctx context.Context, idpConfigID string) error { func (repo *IAMRepository) RemoveIDPConfig(ctx context.Context, idpConfigID string) error {
// if repo.IAMV2 != nil { // if repo.IAMV2Command != nil {
// return repo.IAMV2. // return repo.IAMV2Command.
// } // }
aggregates := make([]*es_models.Aggregate, 0) aggregates := make([]*es_models.Aggregate, 0)
idp := iam_model.NewIDPConfig(repo.SystemDefaults.IamID, idpConfigID) idp := iam_model.NewIDPConfig(repo.SystemDefaults.IamID, idpConfigID)
@ -184,8 +186,8 @@ func (repo *IAMRepository) RemoveIDPConfig(ctx context.Context, idpConfigID stri
func (repo *IAMRepository) ChangeOidcIDPConfig(ctx context.Context, oidcConfig *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) { func (repo *IAMRepository) ChangeOidcIDPConfig(ctx context.Context, oidcConfig *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) {
oidcConfig.AggregateID = repo.SystemDefaults.IamID oidcConfig.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangeIDPOIDCConfig(ctx, oidcConfig) return repo.IAMV2Command.ChangeDefaultIDPOIDCConfig(ctx, oidcConfig)
} }
return repo.IAMEventstore.ChangeIDPOIDCConfig(ctx, oidcConfig) return repo.IAMEventstore.ChangeIDPOIDCConfig(ctx, oidcConfig)
} }
@ -238,16 +240,16 @@ func (repo *IAMRepository) GetDefaultLabelPolicy(ctx context.Context) (*iam_mode
func (repo *IAMRepository) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) { func (repo *IAMRepository) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddLabelPolicy(ctx, policy) return repo.IAMV2Command.AddDefaultLabelPolicy(ctx, policy)
} }
return repo.IAMEventstore.AddLabelPolicy(ctx, policy) return repo.IAMEventstore.AddLabelPolicy(ctx, policy)
} }
func (repo *IAMRepository) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) { func (repo *IAMRepository) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangeLabelPolicy(ctx, policy) return repo.IAMV2Command.ChangeDefaultLabelPolicy(ctx, policy)
} }
return repo.IAMEventstore.ChangeLabelPolicy(ctx, policy) return repo.IAMEventstore.ChangeLabelPolicy(ctx, policy)
} }
@ -279,16 +281,16 @@ func (repo *IAMRepository) GetDefaultLoginPolicy(ctx context.Context) (*iam_mode
func (repo *IAMRepository) AddDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) { func (repo *IAMRepository) AddDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddLoginPolicy(ctx, policy) return repo.IAMV2Command.AddDefaultLoginPolicy(ctx, policy)
} }
return repo.IAMEventstore.AddLoginPolicy(ctx, policy) return repo.IAMEventstore.AddLoginPolicy(ctx, policy)
} }
func (repo *IAMRepository) ChangeDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) { func (repo *IAMRepository) ChangeDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangeLoginPolicy(ctx, policy) return repo.IAMV2Command.ChangeDefaultLoginPolicy(ctx, policy)
} }
return repo.IAMEventstore.ChangeLoginPolicy(ctx, policy) return repo.IAMEventstore.ChangeLoginPolicy(ctx, policy)
} }
@ -317,8 +319,8 @@ func (repo *IAMRepository) SearchDefaultIDPProviders(ctx context.Context, reques
func (repo *IAMRepository) AddIDPProviderToLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) { func (repo *IAMRepository) AddIDPProviderToLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) {
provider.AggregateID = repo.SystemDefaults.IamID provider.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddIDPProviderToLoginPolicy(ctx, provider) return repo.IAMV2Command.AddIDPProviderToDefaultLoginPolicy(ctx, provider)
} }
return repo.IAMEventstore.AddIDPProviderToLoginPolicy(ctx, provider) return repo.IAMEventstore.AddIDPProviderToLoginPolicy(ctx, provider)
} }
@ -360,15 +362,15 @@ func (repo *IAMRepository) SearchDefaultSecondFactors(ctx context.Context) (*iam
} }
func (repo *IAMRepository) AddSecondFactorToLoginPolicy(ctx context.Context, mfa iam_model.SecondFactorType) (iam_model.SecondFactorType, error) { func (repo *IAMRepository) AddSecondFactorToLoginPolicy(ctx context.Context, mfa iam_model.SecondFactorType) (iam_model.SecondFactorType, error) {
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddSecondFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa) return repo.IAMV2Command.AddSecondFactorToDefaultLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
} }
return repo.IAMEventstore.AddSecondFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa) return repo.IAMEventstore.AddSecondFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
} }
func (repo *IAMRepository) RemoveSecondFactorFromLoginPolicy(ctx context.Context, mfa iam_model.SecondFactorType) error { func (repo *IAMRepository) RemoveSecondFactorFromLoginPolicy(ctx context.Context, mfa iam_model.SecondFactorType) error {
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.RemoveSecondFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa) return repo.IAMV2Command.RemoveSecondFactorFromDefaultLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
} }
return repo.IAMEventstore.RemoveSecondFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa) return repo.IAMEventstore.RemoveSecondFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
} }
@ -385,15 +387,15 @@ func (repo *IAMRepository) SearchDefaultMultiFactors(ctx context.Context) (*iam_
} }
func (repo *IAMRepository) AddMultiFactorToLoginPolicy(ctx context.Context, mfa iam_model.MultiFactorType) (iam_model.MultiFactorType, error) { func (repo *IAMRepository) AddMultiFactorToLoginPolicy(ctx context.Context, mfa iam_model.MultiFactorType) (iam_model.MultiFactorType, error) {
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddMultiFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa) return repo.IAMV2Command.AddMultiFactorToDefaultLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
} }
return repo.IAMEventstore.AddMultiFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa) return repo.IAMEventstore.AddMultiFactorToLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
} }
func (repo *IAMRepository) RemoveMultiFactorFromLoginPolicy(ctx context.Context, mfa iam_model.MultiFactorType) error { func (repo *IAMRepository) RemoveMultiFactorFromLoginPolicy(ctx context.Context, mfa iam_model.MultiFactorType) error {
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.RemoveMultiFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa) return repo.IAMV2Command.RemoveMultiFactorFromDefaultLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
} }
return repo.IAMEventstore.RemoveMultiFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa) return repo.IAMEventstore.RemoveMultiFactorFromLoginPolicy(ctx, repo.SystemDefaults.IamID, mfa)
} }
@ -425,16 +427,16 @@ func (repo *IAMRepository) GetDefaultPasswordComplexityPolicy(ctx context.Contex
func (repo *IAMRepository) AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) { func (repo *IAMRepository) AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddPasswordComplexityPolicy(ctx, policy) return repo.IAMV2Command.AddDefaultPasswordComplexityPolicy(ctx, policy)
} }
return repo.IAMEventstore.AddPasswordComplexityPolicy(ctx, policy) return repo.IAMEventstore.AddPasswordComplexityPolicy(ctx, policy)
} }
func (repo *IAMRepository) ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) { func (repo *IAMRepository) ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangePasswordComplexityPolicy(ctx, policy) return repo.IAMV2Command.ChangeDefaultPasswordComplexityPolicy(ctx, policy)
} }
return repo.IAMEventstore.ChangePasswordComplexityPolicy(ctx, policy) return repo.IAMEventstore.ChangePasswordComplexityPolicy(ctx, policy)
} }
@ -466,16 +468,16 @@ func (repo *IAMRepository) GetDefaultPasswordAgePolicy(ctx context.Context) (*ia
func (repo *IAMRepository) AddDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) { func (repo *IAMRepository) AddDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddPasswordAgePolicy(ctx, policy) return repo.IAMV2Command.AddDefaultPasswordAgePolicy(ctx, policy)
} }
return repo.IAMEventstore.AddPasswordAgePolicy(ctx, policy) return repo.IAMEventstore.AddPasswordAgePolicy(ctx, policy)
} }
func (repo *IAMRepository) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) { func (repo *IAMRepository) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangePasswordAgePolicy(ctx, policy) return repo.IAMV2Command.ChangeDefaultPasswordAgePolicy(ctx, policy)
} }
return repo.IAMEventstore.ChangePasswordAgePolicy(ctx, policy) return repo.IAMEventstore.ChangePasswordAgePolicy(ctx, policy)
} }
@ -507,16 +509,16 @@ func (repo *IAMRepository) GetDefaultPasswordLockoutPolicy(ctx context.Context)
func (repo *IAMRepository) AddDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) { func (repo *IAMRepository) AddDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddPasswordLockoutPolicy(ctx, policy) return repo.IAMV2Command.AddDefaultPasswordLockoutPolicy(ctx, policy)
} }
return repo.IAMEventstore.AddPasswordLockoutPolicy(ctx, policy) return repo.IAMEventstore.AddPasswordLockoutPolicy(ctx, policy)
} }
func (repo *IAMRepository) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) { func (repo *IAMRepository) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangePasswordLockoutPolicy(ctx, policy) return repo.IAMV2Command.ChangeDefaultPasswordLockoutPolicy(ctx, policy)
} }
return repo.IAMEventstore.ChangePasswordLockoutPolicy(ctx, policy) return repo.IAMEventstore.ChangePasswordLockoutPolicy(ctx, policy)
} }
@ -548,16 +550,16 @@ func (repo *IAMRepository) GetOrgIAMPolicy(ctx context.Context) (*iam_model.OrgI
func (repo *IAMRepository) AddDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) { func (repo *IAMRepository) AddDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.AddOrgIAMPolicy(ctx, policy) return repo.IAMV2Command.AddDefaultOrgIAMPolicy(ctx, policy)
} }
return repo.IAMEventstore.AddOrgIAMPolicy(ctx, policy) return repo.IAMEventstore.AddOrgIAMPolicy(ctx, policy)
} }
func (repo *IAMRepository) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) { func (repo *IAMRepository) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
policy.AggregateID = repo.SystemDefaults.IamID policy.AggregateID = repo.SystemDefaults.IamID
if repo.IAMV2 != nil { if repo.IAMV2Command != nil {
return repo.IAMV2.ChangeOrgIAMPolicy(ctx, policy) return repo.IAMV2Command.ChangeDefaultOrgIAMPolicy(ctx, policy)
} }
return repo.IAMEventstore.ChangeOrgIAMPolicy(ctx, policy) return repo.IAMEventstore.ChangeOrgIAMPolicy(ctx, policy)
} }

View File

@ -2,6 +2,8 @@ package eventsourcing
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/v2/command"
"github.com/caos/zitadel/internal/v2/query"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/eventstore" "github.com/caos/zitadel/internal/admin/repository/eventsourcing/eventstore"
"github.com/caos/zitadel/internal/admin/repository/eventsourcing/handler" "github.com/caos/zitadel/internal/admin/repository/eventsourcing/handler"
@ -14,7 +16,6 @@ import (
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing" es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing" es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing" es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
) )
type Config struct { type Config struct {
@ -65,7 +66,11 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
if err != nil { if err != nil {
return nil, err return nil, err
} }
iamV2, err := iam_business.StartRepository(&iam_business.Config{Eventstore: esV2, SystemDefaults: systemDefaults}) iamV2Command, err := command.StartCommandSide(&command.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil {
return nil, err
}
iamV2Query, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -90,7 +95,8 @@ func Start(ctx context.Context, conf Config, systemDefaults sd.SystemDefaults, r
SystemDefaults: systemDefaults, SystemDefaults: systemDefaults,
SearchLimit: conf.SearchLimit, SearchLimit: conf.SearchLimit,
Roles: roles, Roles: roles,
IAMV2: iamV2, IAMV2Command: iamV2Command,
IAMV2Query: iamV2Query,
}, },
AdministratorRepo: eventstore.AdministratorRepo{ AdministratorRepo: eventstore.AdministratorRepo{
View: view, View: view,

View File

@ -6,6 +6,7 @@ import (
auth_es "github.com/caos/zitadel/internal/auth/repository/eventsourcing" auth_es "github.com/caos/zitadel/internal/auth/repository/eventsourcing"
"github.com/caos/zitadel/internal/telemetry/metrics" "github.com/caos/zitadel/internal/telemetry/metrics"
"github.com/caos/zitadel/internal/telemetry/metrics/otel" "github.com/caos/zitadel/internal/telemetry/metrics/otel"
"github.com/caos/zitadel/internal/v2/domain"
view_model "github.com/caos/zitadel/internal/view/model" view_model "github.com/caos/zitadel/internal/view/model"
"go.opentelemetry.io/otel/api/metric" "go.opentelemetry.io/otel/api/metric"
"net/http" "net/http"
@ -98,10 +99,10 @@ func (a *API) healthHandler() http.Handler {
if err != nil && !errors.IsNotFound(err) { if err != nil && !errors.IsNotFound(err) {
return errors.ThrowPreconditionFailed(err, "API-dsgT2", "IAM SETUP CHECK FAILED") return errors.ThrowPreconditionFailed(err, "API-dsgT2", "IAM SETUP CHECK FAILED")
} }
if iam == nil || iam.SetUpStarted < iam_model.StepCount-1 { if iam == nil || iam.SetUpStarted < domain.StepCount-1 {
return errors.ThrowPreconditionFailed(nil, "API-HBfs3", "IAM NOT SET UP") return errors.ThrowPreconditionFailed(nil, "API-HBfs3", "IAM NOT SET UP")
} }
if iam.SetUpDone < iam_model.StepCount-1 { if iam.SetUpDone < domain.StepCount-1 {
return errors.ThrowPreconditionFailed(nil, "API-DASs2", "IAM SETUP RUNNING") return errors.ThrowPreconditionFailed(nil, "API-DASs2", "IAM SETUP RUNNING")
} }
return nil return nil

View File

@ -2,6 +2,7 @@ package management
import ( import (
iam_model "github.com/caos/zitadel/internal/iam/model" iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/pkg/grpc/management" "github.com/caos/zitadel/pkg/grpc/management"
) )
@ -14,11 +15,11 @@ func iamFromModel(iam *iam_model.IAM) *management.Iam {
} }
} }
func iamSetupStepFromModel(step iam_model.Step) management.IamSetupStep { func iamSetupStepFromModel(step domain.Step) management.IamSetupStep {
switch step { switch step {
case iam_model.Step1: case domain.Step1:
return management.IamSetupStep_iam_setup_step_1 return management.IamSetupStep_iam_setup_step_1
case iam_model.Step2: case domain.Step2:
return management.IamSetupStep_iam_setup_step_2 return management.IamSetupStep_iam_setup_step_2
// case iam_model.Step3: // case iam_model.Step3:
// return management.IamSetupStep_iam_setup_step_3 // return management.IamSetupStep_iam_setup_step_3

View File

@ -2,17 +2,17 @@ package eventstore
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/v2/query"
"github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/model"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
) )
type IAMRepository struct { type IAMRepository struct {
IAMID string IAMID string
IAMV2 *iam_business.Repository IAMV2QuerySide *query.QuerySide
} }
func (repo *IAMRepository) GetIAM(ctx context.Context) (*model.IAM, error) { func (repo *IAMRepository) GetIAM(ctx context.Context) (*model.IAM, error) {
return repo.IAMV2.IAMByID(ctx, repo.IAMID) return repo.IAMV2QuerySide.IAMByID(ctx, repo.IAMID)
} }

View File

@ -5,13 +5,13 @@ import (
"strings" "strings"
"github.com/caos/logging" "github.com/caos/logging"
"github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing" iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_model "github.com/caos/zitadel/internal/org/model" org_model "github.com/caos/zitadel/internal/org/model"
@ -25,6 +25,7 @@ import (
usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model"
grant_es_model "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing/model" grant_es_model "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model" view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
) )
type UserGrant struct { type UserGrant struct {
@ -308,7 +309,7 @@ func (u *UserGrant) setIamProjectID() error {
return err return err
} }
if iam.SetUpDone < iam_model.StepCount-1 { if iam.SetUpDone < domain.StepCount-1 {
return caos_errs.ThrowPreconditionFailed(nil, "HANDL-s5DTs", "Setup not done") return caos_errs.ThrowPreconditionFailed(nil, "HANDL-s5DTs", "Setup not done")
} }
u.iamProjectID = iam.IAMProjectID u.iamProjectID = iam.IAMProjectID

View File

@ -20,7 +20,7 @@ import (
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing" es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing" es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing" es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam" "github.com/caos/zitadel/internal/v2/query"
) )
type Config struct { type Config struct {
@ -110,7 +110,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, au
return nil, err return nil, err
} }
iamV2, err := iam_business.StartRepository(&iam_business.Config{Eventstore: esV2, SystemDefaults: systemDefaults}) iamV2Query, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -182,8 +182,8 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults, au
SystemDefaults: systemDefaults, SystemDefaults: systemDefaults,
}, },
eventstore.IAMRepository{ eventstore.IAMRepository{
IAMID: systemDefaults.IamID, IAMID: systemDefaults.IamID,
IAMV2: iamV2, IAMV2QuerySide: iamV2Query,
}, },
}, nil }, nil
} }

View File

@ -2,17 +2,17 @@ package eventstore
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/v2/query"
"github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/model"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing" iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
) )
type IamRepo struct { type IamRepo struct {
IAMID string IAMID string
IAMEvents *iam_event.IAMEventstore IAMEvents *iam_event.IAMEventstore
IAMV2 *iam_business.Repository IAMV2Query *query.QuerySide
} }
func (repo *IamRepo) Health(ctx context.Context) error { func (repo *IamRepo) Health(ctx context.Context) error {
@ -20,5 +20,5 @@ func (repo *IamRepo) Health(ctx context.Context) error {
} }
func (repo *IamRepo) IamByID(ctx context.Context) (*model.IAM, error) { func (repo *IamRepo) IamByID(ctx context.Context) (*model.IAM, error) {
return repo.IAMV2.IAMByID(ctx, repo.IAMID) return repo.IAMV2Query.IAMByID(ctx, repo.IAMID)
} }

View File

@ -6,10 +6,10 @@ import (
"github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/authz/repository/eventsourcing/view" "github.com/caos/zitadel/internal/authz/repository/eventsourcing/view"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing" iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
grant_model "github.com/caos/zitadel/internal/usergrant/model" grant_model "github.com/caos/zitadel/internal/usergrant/model"
"github.com/caos/zitadel/internal/usergrant/repository/view/model" "github.com/caos/zitadel/internal/usergrant/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
) )
type UserGrantRepo struct { type UserGrantRepo struct {
@ -72,7 +72,7 @@ func (repo *UserGrantRepo) FillIamProjectID(ctx context.Context) error {
if err != nil { if err != nil {
return err return err
} }
if iam.SetUpDone < iam_model.StepCount-1 { if iam.SetUpDone < domain.StepCount-1 {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-skiwS", "Setup not done") return caos_errs.ThrowPreconditionFailed(nil, "EVENT-skiwS", "Setup not done")
} }
repo.IamProjectID = iam.IAMProjectID repo.IamProjectID = iam.IAMProjectID

View File

@ -12,12 +12,12 @@ import (
"github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/eventstore/spooler"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing" iam_events "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model"
proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model"
view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model" view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model"
"github.com/caos/zitadel/internal/v2/domain"
) )
type UserGrant struct { type UserGrant struct {
@ -224,7 +224,7 @@ func (u *UserGrant) setIamProjectID() error {
if err != nil { if err != nil {
return err return err
} }
if iam.SetUpDone < iam_model.StepCount-1 { if iam.SetUpDone < domain.StepCount-1 {
return caos_errs.ThrowPreconditionFailed(nil, "HANDL-s5DTs", "Setup not done") return caos_errs.ThrowPreconditionFailed(nil, "HANDL-s5DTs", "Setup not done")
} }
u.iamProjectID = iam.IAMProjectID u.iamProjectID = iam.IAMProjectID

View File

@ -2,6 +2,7 @@ package eventsourcing
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/v2/query"
es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing" es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing"
@ -19,7 +20,6 @@ import (
"github.com/caos/zitadel/internal/id" "github.com/caos/zitadel/internal/id"
es_key "github.com/caos/zitadel/internal/key/repository/eventsourcing" es_key "github.com/caos/zitadel/internal/key/repository/eventsourcing"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing" es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
) )
type Config struct { type Config struct {
@ -79,7 +79,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults) (*
if err != nil { if err != nil {
return nil, err return nil, err
} }
iamV2, err := iam_business.StartRepository(&iam_business.Config{Eventstore: esV2, SystemDefaults: systemDefaults}) iamV2, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -96,9 +96,9 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults) (*
IamEvents: iam, IamEvents: iam,
}, },
eventstore.IamRepo{ eventstore.IamRepo{
IAMID: systemDefaults.IamID, IAMID: systemDefaults.IamID,
IAMEvents: iam, IAMEvents: iam,
IAMV2: iamV2, IAMV2Query: iamV2,
}, },
eventstore.TokenVerifierRepo{ eventstore.TokenVerifierRepo{
//TODO: Add Token Verification Key //TODO: Add Token Verification Key

View File

@ -59,7 +59,7 @@ func (data *Data) createTemplate(templateName string, file *os.File) {
} }
func readErrorName() (errorName string) { func readErrorName() (errorName string) {
flag.StringVar(&errorName, "Name", "", "Type of the error (e.g. Internal)") flag.StringVar(&errorName, "Name", "", "KeyType of the error (e.g. Internal)")
flag.Parse() flag.Parse()
return errorName return errorName
} }

View File

@ -3,7 +3,7 @@ package eventstore
type aggregater interface { type aggregater interface {
//ID returns the aggreagte id //ID returns the aggreagte id
ID() string ID() string
//Type returns the aggregate type //KeyType returns the aggregate type
Type() AggregateType Type() AggregateType
//Events returns the events which will be pushed //Events returns the events which will be pushed
Events() []EventPusher Events() []EventPusher
@ -74,7 +74,7 @@ func (a *Aggregate) ID() string {
return a.id return a.id
} }
//Type implements aggregater //KeyType implements aggregater
func (a *Aggregate) Type() AggregateType { func (a *Aggregate) Type() AggregateType {
return a.typ return a.typ
} }

View File

@ -9,7 +9,7 @@ type EventPusher interface {
EditorService() string EditorService() string
//EditorUser is the user who wants to push the event //EditorUser is the user who wants to push the event
EditorUser() string EditorUser() string
//Type must return an event type which should be unique in the aggregate //KeyType must return an event type which should be unique in the aggregate
Type() EventType Type() EventType
//Data returns the payload of the event. It represent the changed fields by the event //Data returns the payload of the event. It represent the changed fields by the event
// valid types are: // valid types are:
@ -25,7 +25,7 @@ type EventReader interface {
EditorService() string EditorService() string
//EditorUser is the user who pushed the event //EditorUser is the user who pushed the event
EditorUser() string EditorUser() string
//Type is the type of the event //KeyType is the type of the event
Type() EventType Type() EventType
AggregateID() string AggregateID() string

View File

@ -36,7 +36,7 @@ func (e *BaseEvent) EditorUser() string {
return e.User return e.User
} }
//Type implements EventPusher //KeyType implements EventPusher
func (e *BaseEvent) Type() EventType { func (e *BaseEvent) Type() EventType {
return e.EventType return e.EventType
} }

View File

@ -6,7 +6,7 @@ import (
"log" "log"
) )
//ReadModel is the minimum representation of a View model. //MemberReadModel is the minimum representation of a View model.
// it might be saved in a database or in memory // it might be saved in a database or in memory
type ReadModel struct { type ReadModel struct {
ProcessedSequence uint64 ProcessedSequence uint64

View File

@ -2,7 +2,7 @@ package eventstore
import "time" import "time"
//ReadModel is the minimum representation of a View model. //MemberReadModel is the minimum representation of a View model.
// It implements a basic reducer // It implements a basic reducer
// it might be saved in a database or in memory // it might be saved in a database or in memory
type ReadModel struct { type ReadModel struct {

View File

@ -26,7 +26,7 @@ type Event struct {
// time drifts in different services could cause integrity problems // time drifts in different services could cause integrity problems
CreationDate time.Time CreationDate time.Time
//Type describes the cause of the event (e.g. user.added) //KeyType describes the cause of the event (e.g. user.added)
// it should always be in past-form // it should always be in past-form
Type EventType Type EventType

View File

@ -2,7 +2,7 @@ package eventstore
import "time" import "time"
//WriteModel is the minimum representation of a command side view model. //MemberWriteModel is the minimum representation of a command side view model.
// It implements a basic reducer // It implements a basic reducer
// it's purpose is to reduce events to create new ones // it's purpose is to reduce events to create new ones
type WriteModel struct { type WriteModel struct {

View File

@ -2,6 +2,7 @@ package model
import ( import (
es_models "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/v2/domain"
) )
type Step int type Step int
@ -23,8 +24,8 @@ type IAM struct {
es_models.ObjectRoot es_models.ObjectRoot
GlobalOrgID string GlobalOrgID string
IAMProjectID string IAMProjectID string
SetUpDone Step SetUpDone domain.Step
SetUpStarted Step SetUpStarted domain.Step
Members []*IAMMember Members []*IAMMember
IDPs []*IDPConfig IDPs []*IDPConfig
DefaultLoginPolicy *LoginPolicy DefaultLoginPolicy *LoginPolicy

View File

@ -22,6 +22,8 @@ type PasswordComplexityPolicy struct {
HasUppercase bool HasUppercase bool
HasNumber bool HasNumber bool
HasSymbol bool HasSymbol bool
Default bool
} }
func (p *PasswordComplexityPolicy) IsValid() error { func (p *PasswordComplexityPolicy) IsValid() error {
@ -30,3 +32,26 @@ func (p *PasswordComplexityPolicy) IsValid() error {
} }
return nil return nil
} }
func (p *PasswordComplexityPolicy) Check(password string) error {
if p.MinLength != 0 && uint64(len(password)) < p.MinLength {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-HuJf6", "Errors.User.PasswordComplexityPolicy.MinLength")
}
if p.HasLowercase && !hasStringLowerCase(password) {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-co3Xw", "Errors.User.PasswordComplexityPolicy.HasLower")
}
if p.HasUppercase && !hasStringUpperCase(password) {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-VoaRj", "Errors.User.PasswordComplexityPolicy.HasUpper")
}
if p.HasNumber && !hasNumber(password) {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-ZBv4H", "Errors.User.PasswordComplexityPolicy.HasNumber")
}
if p.HasSymbol && !hasSymbol(password) {
return caos_errs.ThrowInvalidArgument(nil, "MODEL-ZDLwA", "Errors.User.PasswordComplexityPolicy.HasSymbol")
}
return nil
}

View File

@ -73,49 +73,49 @@ func (es *IAMEventstore) IAMEventsByID(ctx context.Context, id string, sequence
return es.FilterEvents(ctx, query) return es.FilterEvents(ctx, query)
} }
func (es *IAMEventstore) StartSetup(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) { //func (es *IAMEventstore) StartSetup(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
iam, err := es.IAMByID(ctx, iamID) // iam, err := es.IAMByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) { // if err != nil && !caos_errs.IsNotFound(err) {
return nil, err // return nil, err
} // }
//
if iam != nil && (iam.SetUpStarted >= step || iam.SetUpStarted != iam.SetUpDone) { // if iam != nil && (iam.SetUpStarted >= step || iam.SetUpStarted != iam.SetUpDone) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "Setup already started") // return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "Setup already started")
} // }
//
if iam == nil { // if iam == nil {
iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: iamID}} // iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: iamID}}
} // }
iam.SetUpStarted = step // iam.SetUpStarted = step
repoIAM := model.IAMFromModel(iam) // repoIAM := model.IAMFromModel(iam)
//
createAggregate := IAMSetupStartedAggregate(es.AggregateCreator(), repoIAM) // createAggregate := IAMSetupStartedAggregate(es.AggregateCreator(), repoIAM)
err = es_sdk.Push(ctx, es.PushAggregates, repoIAM.AppendEvents, createAggregate) // err = es_sdk.Push(ctx, es.PushAggregates, repoIAM.AppendEvents, createAggregate)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
//
es.iamCache.cacheIAM(repoIAM) // es.iamCache.cacheIAM(repoIAM)
return model.IAMToModel(repoIAM), nil // return model.IAMToModel(repoIAM), nil
} //}
//
func (es *IAMEventstore) SetupDone(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) { //func (es *IAMEventstore) SetupDone(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
iam, err := es.IAMByID(ctx, iamID) // iam, err := es.IAMByID(ctx, iamID)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
iam.SetUpDone = step // iam.SetUpDone = step
//
repoIam := model.IAMFromModel(iam) // repoIam := model.IAMFromModel(iam)
createAggregate := IAMSetupDoneAggregate(es.AggregateCreator(), repoIam) // createAggregate := IAMSetupDoneAggregate(es.AggregateCreator(), repoIam)
err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, createAggregate) // err = es_sdk.Push(ctx, es.PushAggregates, repoIam.AppendEvents, createAggregate)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
//
es.iamCache.cacheIAM(repoIam) // es.iamCache.cacheIAM(repoIam)
return model.IAMToModel(repoIam), nil // return model.IAMToModel(repoIam), nil
} //}
func (es *IAMEventstore) PrepareSetupDone(ctx context.Context, iam *model.IAM, aggregate *models.Aggregate, step iam_model.Step) (*model.IAM, *models.Aggregate, func(ctx context.Context, aggregates ...*models.Aggregate) error, error) { func (es *IAMEventstore) PrepareSetupDone(ctx context.Context, iam *model.IAM, aggregate *models.Aggregate, step iam_model.Step) (*model.IAM, *models.Aggregate, func(ctx context.Context, aggregates ...*models.Aggregate) error, error) {
iam.SetUpDone = model.Step(step) iam.SetUpDone = model.Step(step)

View File

@ -1562,7 +1562,7 @@ func TestAddIdpProviderToLoginPolicy(t *testing.T) {
t.Errorf("got wrong result IDPConfigID: expected: %v, actual: %v ", tt.res.result.IDPConfigID, result.IDPConfigID) t.Errorf("got wrong result IDPConfigID: expected: %v, actual: %v ", tt.res.result.IDPConfigID, result.IDPConfigID)
} }
if result.Type != tt.res.result.Type { if result.Type != tt.res.result.Type {
t.Errorf("got wrong result Type: expected: %v, actual: %v ", tt.res.result.Type, result.Type) t.Errorf("got wrong result KeyType: expected: %v, actual: %v ", tt.res.result.Type, result.Type)
} }
}) })
} }

View File

@ -7,6 +7,7 @@ import (
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
) )
const ( const (
@ -75,8 +76,8 @@ func IAMToModel(iam *IAM) *model.IAM {
idps := IDPConfigsToModel(iam.IDPs) idps := IDPConfigsToModel(iam.IDPs)
converted := &model.IAM{ converted := &model.IAM{
ObjectRoot: iam.ObjectRoot, ObjectRoot: iam.ObjectRoot,
SetUpStarted: model.Step(iam.SetUpStarted), SetUpStarted: domain.Step(iam.SetUpStarted),
SetUpDone: model.Step(iam.SetUpDone), SetUpDone: domain.Step(iam.SetUpDone),
GlobalOrgID: iam.GlobalOrgID, GlobalOrgID: iam.GlobalOrgID,
IAMProjectID: iam.IAMProjectID, IAMProjectID: iam.IAMProjectID,
Members: members, Members: members,

View File

@ -2,15 +2,15 @@ package eventstore
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/v2/query"
iam_model "github.com/caos/zitadel/internal/iam/model" iam_model "github.com/caos/zitadel/internal/iam/model"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
) )
type IAMRepository struct { type IAMRepository struct {
IAMV2 *iam_business.Repository IAMV2Query *query.QuerySide
} }
func (repo *IAMRepository) IAMByID(ctx context.Context, id string) (*iam_model.IAM, error) { func (repo *IAMRepository) IAMByID(ctx context.Context, id string) (*iam_model.IAM, error) {
return repo.IAMV2.IAMByID(ctx, id) return repo.IAMV2Query.IAMByID(ctx, id)
} }

View File

@ -2,6 +2,7 @@ package eventsourcing
import ( import (
"context" "context"
"github.com/caos/zitadel/internal/v2/query"
sd "github.com/caos/zitadel/internal/config/systemdefaults" sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/config/types" "github.com/caos/zitadel/internal/config/types"
@ -17,7 +18,6 @@ import (
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing" es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing" es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
es_grant "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing" es_grant "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing"
iam_business "github.com/caos/zitadel/internal/v2/business/iam"
) )
type Config struct { type Config struct {
@ -75,7 +75,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe
if err != nil { if err != nil {
return nil, err return nil, err
} }
iamV2, err := iam_business.StartRepository(&iam_business.Config{Eventstore: esV2, SystemDefaults: systemDefaults}) iamV2Query, err := query.StartQuerySide(&query.Config{Eventstore: esV2, SystemDefaults: systemDefaults})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -98,7 +98,7 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, roles []string) (*EsRe
UserRepo: eventstore.UserRepo{es, conf.SearchLimit, user, org, usergrant, view, systemDefaults}, UserRepo: eventstore.UserRepo{es, conf.SearchLimit, user, org, usergrant, view, systemDefaults},
UserGrantRepo: eventstore.UserGrantRepo{conf.SearchLimit, usergrant, view}, UserGrantRepo: eventstore.UserGrantRepo{conf.SearchLimit, usergrant, view},
IAMRepository: eventstore.IAMRepository{ IAMRepository: eventstore.IAMRepository{
IAMV2: iamV2, IAMV2Query: iamV2Query,
}, },
}, nil }, nil
} }

View File

@ -32,9 +32,9 @@ func (msg *EmailMessage) GetContent() string {
} }
//default mime-type is html //default mime-type is html
mime := "MIME-version: 1.0;" + lineBreak + "Content-Type: text/html; charset=\"UTF-8\";" + lineBreak + lineBreak mime := "MIME-version: 1.0;" + lineBreak + "Content-KeyType: text/html; charset=\"UTF-8\";" + lineBreak + lineBreak
if !isHTML(msg.Content) { if !isHTML(msg.Content) {
mime = "MIME-version: 1.0;" + lineBreak + "Content-Type: text/plain; charset=\"UTF-8\";" + lineBreak + lineBreak mime = "MIME-version: 1.0;" + lineBreak + "Content-KeyType: text/plain; charset=\"UTF-8\";" + lineBreak + lineBreak
} }
subject := "Subject: " + msg.Subject + lineBreak subject := "Subject: " + msg.Subject + lineBreak
message += subject + mime + lineBreak + msg.Content message += subject + mime + lineBreak + msg.Content

View File

@ -2637,7 +2637,7 @@ func TestAddIdpProviderToLoginPolicy(t *testing.T) {
t.Errorf("got wrong result IDPConfigID: expected: %v, actual: %v ", tt.res.result.IDPConfigID, result.IDPConfigID) t.Errorf("got wrong result IDPConfigID: expected: %v, actual: %v ", tt.res.result.IDPConfigID, result.IDPConfigID)
} }
if result.Type != tt.res.result.Type { if result.Type != tt.res.result.Type {
t.Errorf("got wrong result Type: expected: %v, actual: %v ", tt.res.result.Type, result.Type) t.Errorf("got wrong result KeyType: expected: %v, actual: %v ", tt.res.result.Type, result.Type)
} }
}) })
} }

View File

@ -314,7 +314,7 @@ func TestLoginPolicyIdpProviderAddedAggregate(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
agg, err := LoginPolicyIDPProviderAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "IAMID")(tt.args.ctx) agg, err := LoginPolicyIDPProviderAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "iamID")(tt.args.ctx)
if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) { if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err) t.Errorf("got wrong err: %v ", err)
return return
@ -509,7 +509,7 @@ func TestLoginPolicySecondFactorAddedAggregate(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
agg, err := LoginPolicySecondFactorAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "IAMID")(tt.args.ctx) agg, err := LoginPolicySecondFactorAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "iamID")(tt.args.ctx)
if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) { if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err) t.Errorf("got wrong err: %v ", err)
return return
@ -682,7 +682,7 @@ func TestLoginPolicyMultiFactorAddedAggregate(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
agg, err := LoginPolicyMultiFactorAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "IAMID")(tt.args.ctx) agg, err := LoginPolicyMultiFactorAddedAggregate(tt.args.aggCreator, tt.args.existing, tt.args.new, "iamID")(tt.args.ctx)
if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) { if tt.res.wantErr && !tt.res.errFunc(err) || (err != nil && !tt.res.wantErr) {
t.Errorf("got wrong err: %v ", err) t.Errorf("got wrong err: %v ", err)
return return

View File

@ -7,28 +7,28 @@ import (
type IAMSetUp struct { type IAMSetUp struct {
Step1 *Step1 Step1 *Step1
Step2 *Step2 //Step2 *Step2
Step3 *Step3 //Step3 *Step3
Step4 *Step4 //Step4 *Step4
Step5 *Step5 //Step5 *Step5
Step6 *Step6 //Step6 *Step6
Step7 *Step7 //Step7 *Step7
Step8 *Step8 //Step8 *Step8
} }
func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]step, error) { func (setup *IAMSetUp) steps(currentDone iam_model.Step) ([]stepV2, error) {
steps := make([]step, 0) steps := make([]stepV2, 0)
missingSteps := make([]iam_model.Step, 0) missingSteps := make([]iam_model.Step, 0)
for _, step := range []step{ for _, step := range []stepV2{
setup.Step1, setup.Step1,
setup.Step2, //setup.Step2,
setup.Step3, //setup.Step3,
setup.Step4, //setup.Step4,
setup.Step5, //setup.Step5,
setup.Step6, //setup.Step6,
setup.Step7, //setup.Step7,
setup.Step8, //setup.Step8,
} { } {
if step.step() <= currentDone { if step.step() <= currentDone {
continue continue

View File

@ -3,24 +3,12 @@ package setup
import ( import (
"context" "context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz" "github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing" iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
es_org "github.com/caos/zitadel/internal/org/repository/eventsourcing"
org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing" org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing"
proj_model "github.com/caos/zitadel/internal/project/model"
es_proj "github.com/caos/zitadel/internal/project/repository/eventsourcing"
proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing"
es_usr "github.com/caos/zitadel/internal/user/repository/eventsourcing"
usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing" usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing"
"github.com/caos/zitadel/internal/v2/command"
) )
type Setup struct { type Setup struct {
@ -29,6 +17,8 @@ type Setup struct {
OrgEvents *org_event.OrgEventstore OrgEvents *org_event.OrgEventstore
UserEvents *usr_event.UserEventstore UserEvents *usr_event.UserEventstore
ProjectEvents *proj_event.ProjectEventstore ProjectEvents *proj_event.ProjectEventstore
Commands *command.CommandSide
} }
const ( const (
@ -48,168 +38,169 @@ const (
OIDCAuthMethodTypePost = "POST" OIDCAuthMethodTypePost = "POST"
) )
func StartSetup(esConfig es_int.Config, sd systemdefaults.SystemDefaults) (*Setup, error) { //
setup := &Setup{ //func StartSetup(esConfig es_int.Config, sd systemdefaults.SystemDefaults) (*Setup, error) {
iamID: sd.IamID, // setup := &Setup{
} // iamID: sd.IamID,
es, err := es_int.Start(esConfig) // }
if err != nil { // es, err := es_int.Start(esConfig)
return nil, err // if err != nil {
} // return nil, err
// }
setup.IamEvents, err = es_iam.StartIAM(es_iam.IAMConfig{ //
Eventstore: es, // setup.IamEvents, err = es_iam.StartIAM(es_iam.IAMConfig{
Cache: esConfig.Cache, // Eventstore: es,
}, sd) // Cache: esConfig.Cache,
if err != nil { // }, sd)
return nil, err // if err != nil {
} // return nil, err
// }
setup.OrgEvents = es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: sd.Domain}, sd) //
// setup.OrgEvents = es_org.StartOrg(es_org.OrgConfig{Eventstore: es, IAMDomain: sd.Domain}, sd)
setup.ProjectEvents, err = es_proj.StartProject(es_proj.ProjectConfig{ //
Eventstore: es, // setup.ProjectEvents, err = es_proj.StartProject(es_proj.ProjectConfig{
Cache: esConfig.Cache, // Eventstore: es,
}, sd) // Cache: esConfig.Cache,
if err != nil { // }, sd)
return nil, err // if err != nil {
} // return nil, err
// }
setup.UserEvents, err = es_usr.StartUser(es_usr.UserConfig{ //
Eventstore: es, // setup.UserEvents, err = es_usr.StartUser(es_usr.UserConfig{
Cache: esConfig.Cache, // Eventstore: es,
}, sd) // Cache: esConfig.Cache,
if err != nil { // }, sd)
return nil, err // if err != nil {
} // return nil, err
// }
return setup, nil //
} // return setup, nil
//}
func (s *Setup) Execute(ctx context.Context, setUpConfig IAMSetUp) error { //
logging.Log("SETUP-hwG32").Info("starting setup") //func (s *Setup) Execute(ctx context.Context, setUpConfig IAMSetUp) error {
// logging.Log("SETUP-hwG32").Info("starting setup")
iam, err := s.IamEvents.IAMByID(ctx, s.iamID) //
if err != nil && !caos_errs.IsNotFound(err) { // iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
return err // if err != nil && !caos_errs.IsNotFound(err) {
} // return err
if iam != nil && (iam.SetUpDone == iam_model.StepCount-1 || iam.SetUpStarted != iam.SetUpDone) { // }
logging.Log("SETUP-cWEsn").Info("all steps done") // if iam != nil && (iam.SetUpDone == domain.Step(iam_model.StepCount)-1 || iam.SetUpStarted != iam.SetUpDone) {
return nil // logging.Log("SETUP-cWEsn").Info("all steps done")
} // return nil
// }
if iam == nil { //
iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: s.iamID}} // if iam == nil {
} // iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: s.iamID}}
// }
steps, err := setUpConfig.steps(iam.SetUpDone) //
if err != nil || len(steps) == 0 { // steps, err := setUpConfig.steps(iam_model.Step(iam.SetUpDone))
return err // if err != nil || len(steps) == 0 {
} // return err
// }
ctx = setSetUpContextData(ctx, s.iamID) //
// ctx = setSetUpContextData(ctx, s.iamID)
for _, step := range steps { //
step.init(s) // for _, step := range steps {
if step.step() != iam.SetUpDone+1 { // step.init(s)
logging.LogWithFields("SETUP-rxRM1", "step", step.step(), "previous", iam.SetUpDone).Warn("wrong step order") // if step.step() != iam_model.Step(iam.SetUpDone)+1 {
return errors.ThrowPreconditionFailed(nil, "SETUP-wwAqO", "too few steps for this zitadel verison") // logging.LogWithFields("SETUP-rxRM1", "step", step.step(), "previous", iam.SetUpDone).Warn("wrong step order")
} // return errors.ThrowPreconditionFailed(nil, "SETUP-wwAqO", "too few steps for this zitadel verison")
iam, err = s.IamEvents.StartSetup(ctx, s.iamID, step.step()) // }
if err != nil { // iam, err = s.IamEvents.StartSetup(ctx, s.iamID, step.step())
return err // if err != nil {
} // return err
// }
iam, err = step.execute(ctx) //
if err != nil { // iam, err = step.execute(ctx)
return err // if err != nil {
} // return err
// }
err = s.validateExecutedStep(ctx) //
if err != nil { // err = s.validateExecutedStep(ctx)
return err // if err != nil {
} // return err
} // }
// }
logging.Log("SETUP-ds31h").Info("setup done") //
return nil // logging.Log("SETUP-ds31h").Info("setup done")
} // return nil
//}
func (s *Setup) validateExecutedStep(ctx context.Context) error { //
iam, err := s.IamEvents.IAMByID(ctx, s.iamID) //func (s *Setup) validateExecutedStep(ctx context.Context) error {
if err != nil { // iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
return err // if err != nil {
} // return err
if iam.SetUpStarted != iam.SetUpDone { // }
return errors.ThrowInternal(nil, "SETUP-QeukK", "started step is not equal to done") // if iam.SetUpStarted != iam.SetUpDone {
} // return errors.ThrowInternal(nil, "SETUP-QeukK", "started step is not equal to done")
return nil // }
} // return nil
//}
func getOIDCResponseTypes(responseTypes []string) []proj_model.OIDCResponseType { //
types := make([]proj_model.OIDCResponseType, len(responseTypes)) //func getOIDCResponseTypes(responseTypes []string) []proj_model.OIDCResponseType {
for i, t := range responseTypes { // types := make([]proj_model.OIDCResponseType, len(responseTypes))
types[i] = getOIDCResponseType(t) // for i, t := range responseTypes {
} // types[i] = getOIDCResponseType(t)
return types // }
} // return types
//}
func getOIDCResponseType(responseType string) proj_model.OIDCResponseType { //
switch responseType { //func getOIDCResponseType(responseType string) proj_model.OIDCResponseType {
case OIDCResponseTypeCode: // switch responseType {
return proj_model.OIDCResponseTypeCode // case OIDCResponseTypeCode:
case OIDCResponseTypeIDToken: // return proj_model.OIDCResponseTypeCode
return proj_model.OIDCResponseTypeIDToken // case OIDCResponseTypeIDToken:
case OIDCResponseTypeToken: // return proj_model.OIDCResponseTypeIDToken
return proj_model.OIDCResponseTypeIDTokenToken // case OIDCResponseTypeToken:
} // return proj_model.OIDCResponseTypeIDTokenToken
return proj_model.OIDCResponseTypeCode // }
} // return proj_model.OIDCResponseTypeCode
//}
func getOIDCGrantTypes(grantTypes []string) []proj_model.OIDCGrantType { //
types := make([]proj_model.OIDCGrantType, len(grantTypes)) //func getOIDCGrantTypes(grantTypes []string) []proj_model.OIDCGrantType {
for i, t := range grantTypes { // types := make([]proj_model.OIDCGrantType, len(grantTypes))
types[i] = getOIDCGrantType(t) // for i, t := range grantTypes {
} // types[i] = getOIDCGrantType(t)
return types // }
} // return types
//}
func getOIDCGrantType(grantTypes string) proj_model.OIDCGrantType { //
switch grantTypes { //func getOIDCGrantType(grantTypes string) proj_model.OIDCGrantType {
case OIDCGrantTypeAuthorizationCode: // switch grantTypes {
return proj_model.OIDCGrantTypeAuthorizationCode // case OIDCGrantTypeAuthorizationCode:
case OIDCGrantTypeImplicit: // return proj_model.OIDCGrantTypeAuthorizationCode
return proj_model.OIDCGrantTypeImplicit // case OIDCGrantTypeImplicit:
case OIDCGrantTypeRefreshToken: // return proj_model.OIDCGrantTypeImplicit
return proj_model.OIDCGrantTypeRefreshToken // case OIDCGrantTypeRefreshToken:
} // return proj_model.OIDCGrantTypeRefreshToken
return proj_model.OIDCGrantTypeAuthorizationCode // }
} // return proj_model.OIDCGrantTypeAuthorizationCode
//}
func getOIDCApplicationType(appType string) proj_model.OIDCApplicationType { //
switch appType { //func getOIDCApplicationType(appType string) proj_model.OIDCApplicationType {
case OIDCApplicationTypeNative: // switch appType {
return proj_model.OIDCApplicationTypeNative // case OIDCApplicationTypeNative:
case OIDCApplicationTypeUserAgent: // return proj_model.OIDCApplicationTypeNative
return proj_model.OIDCApplicationTypeUserAgent // case OIDCApplicationTypeUserAgent:
case OIDCApplicationTypeWeb: // return proj_model.OIDCApplicationTypeUserAgent
return proj_model.OIDCApplicationTypeWeb // case OIDCApplicationTypeWeb:
} // return proj_model.OIDCApplicationTypeWeb
return proj_model.OIDCApplicationTypeWeb // }
} // return proj_model.OIDCApplicationTypeWeb
//}
func getOIDCAuthMethod(authMethod string) proj_model.OIDCAuthMethodType { //
switch authMethod { //func getOIDCAuthMethod(authMethod string) proj_model.OIDCAuthMethodType {
case OIDCAuthMethodTypeNone: // switch authMethod {
return proj_model.OIDCAuthMethodTypeNone // case OIDCAuthMethodTypeNone:
case OIDCAuthMethodTypeBasic: // return proj_model.OIDCAuthMethodTypeNone
return proj_model.OIDCAuthMethodTypeBasic // case OIDCAuthMethodTypeBasic:
case OIDCAuthMethodTypePost: // return proj_model.OIDCAuthMethodTypeBasic
return proj_model.OIDCAuthMethodTypePost // case OIDCAuthMethodTypePost:
} // return proj_model.OIDCAuthMethodTypePost
return proj_model.OIDCAuthMethodTypeBasic // }
} // return proj_model.OIDCAuthMethodTypeBasic
//}
//
func setSetUpContextData(ctx context.Context, orgID string) context.Context { func setSetUpContextData(ctx context.Context, orgID string) context.Context {
return authz.SetCtxData(ctx, authz.CtxData{UserID: SetupUser, OrgID: orgID}) return authz.SetCtxData(ctx, authz.CtxData{UserID: SetupUser, OrgID: orgID})
} }

104
internal/setup/setup_v2.go Normal file
View File

@ -0,0 +1,104 @@
package setup
import (
"context"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/config/systemdefaults"
caos_errs "github.com/caos/zitadel/internal/errors"
es_int "github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model"
es_iam "github.com/caos/zitadel/internal/iam/repository/eventsourcing"
"github.com/caos/zitadel/internal/v2/command"
"github.com/caos/zitadel/internal/v2/domain"
)
func StartSetupV2(esConfig es_int.Config, sd systemdefaults.SystemDefaults) (*Setup, error) {
setup := &Setup{
iamID: sd.IamID,
}
es, err := es_int.Start(esConfig)
if err != nil {
return nil, err
}
setup.IamEvents, err = es_iam.StartIAM(es_iam.IAMConfig{
Eventstore: es,
Cache: esConfig.Cache,
}, sd)
if err != nil {
return nil, err
}
setup.Commands, err = command.StartCommandSide(&command.Config{
Eventstore: es.V2(),
SystemDefaults: sd,
})
if err != nil {
return nil, err
}
return setup, nil
}
func (s *Setup) ExecuteV2(ctx context.Context, setUpConfig IAMSetUp) error {
logging.Log("SETUP-JAK2q").Info("starting setup")
iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return err
}
if iam != nil && (iam.SetUpDone == domain.StepCount-1 || iam.SetUpStarted != iam.SetUpDone) {
logging.Log("SETUP-VA2k1").Info("all steps done")
return nil
}
if iam == nil {
iam = &iam_model.IAM{ObjectRoot: models.ObjectRoot{AggregateID: s.iamID}}
}
steps, err := setUpConfig.steps(iam_model.Step(iam.SetUpDone))
if err != nil || len(steps) == 0 {
return err
}
ctx = setSetUpContextData(ctx, s.iamID)
for _, step := range steps {
//step.init(s)
if step.step() != iam_model.Step(iam.SetUpDone+1) {
logging.LogWithFields("SETUP-rxRM1", "step", step.step(), "previous", iam.SetUpDone).Warn("wrong step order")
return caos_errs.ThrowPreconditionFailed(nil, "SETUP-wwAqO", "too few steps for this zitadel verison")
}
iam, err = s.Commands.StartSetup(ctx, s.iamID, domain.Step(step.step()))
if err != nil {
return err
}
err = step.execute(ctx, iam.AggregateID, *s.Commands)
if err != nil {
return err
}
err = s.validateExecutedStep(ctx)
if err != nil {
return err
}
}
logging.Log("SETUP-ds31h").Info("setup done")
return nil
}
func (s *Setup) validateExecutedStep(ctx context.Context) error {
iam, err := s.IamEvents.IAMByID(ctx, s.iamID)
if err != nil {
return err
}
if iam.SetUpStarted != iam.SetUpDone {
return caos_errs.ThrowInternal(nil, "SETUP-QeukK", "started step is not equal to done")
}
return nil
}

View File

@ -4,6 +4,7 @@ import (
"context" "context"
iam_model "github.com/caos/zitadel/internal/iam/model" iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/command"
) )
type step interface { type step interface {
@ -12,3 +13,9 @@ type step interface {
init(*Setup) init(*Setup)
isNil() bool isNil() bool
} }
type stepV2 interface {
step() iam_model.Step
execute(context.Context, string, command.CommandSide) error
isNil() bool
}

View File

@ -4,322 +4,287 @@ import (
"context" "context"
"github.com/caos/logging" "github.com/caos/logging"
"github.com/caos/zitadel/internal/api/authz"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
iam_model "github.com/caos/zitadel/internal/iam/model" iam_model "github.com/caos/zitadel/internal/iam/model"
org_model "github.com/caos/zitadel/internal/org/model" "github.com/caos/zitadel/internal/v2/command"
proj_model "github.com/caos/zitadel/internal/project/model"
usr_model "github.com/caos/zitadel/internal/user/model"
) )
type Step1 struct { type Step1 struct {
GlobalOrg string //GlobalOrg string
IAMProject string //IAMProject string
DefaultLoginPolicy LoginPolicy //DefaultLoginPolicy LoginPolicy
Orgs []Org //Orgs []Org
Owners []string //Owners []string
command.Step1
setup *Setup //setup *Setup
createdUsers map[string]*usr_model.User //createdUsers map[string]*usr_model.User
createdOrgs map[string]*org_model.Org //createdOrgs map[string]*org_model.Org
createdProjects map[string]*proj_model.Project //createdProjects map[string]*proj_model.Project
pwComplexityPolicy *iam_model.PasswordComplexityPolicyView //pwComplexityPolicy *iam_model.PasswordComplexityPolicyView
} }
func (s *Step1) isNil() bool { func (s *Step1) isNil() bool {
return s == nil return s == nil
} }
func (step *Step1) step() iam_model.Step { func (s *Step1) step() iam_model.Step {
return iam_model.Step1 return iam_model.Step1
} }
func (step *Step1) init(setup *Setup) { //func (s *Step1) init(setup *Setup) {
step.setup = setup // s.setup = setup
step.createdUsers = make(map[string]*usr_model.User) // s.createdUsers = make(map[string]*usr_model.User)
step.createdOrgs = make(map[string]*org_model.Org) // s.createdOrgs = make(map[string]*org_model.Org)
step.createdProjects = make(map[string]*proj_model.Project) // s.createdProjects = make(map[string]*proj_model.Project)
} //}
func (step *Step1) execute(ctx context.Context) (*iam_model.IAM, error) { func (s *Step1) execute(ctx context.Context, iamID string, commands command.CommandSide) error {
err := step.loginPolicy(ctx, step.DefaultLoginPolicy) err := commands.SetupStep1(ctx, iamID, s.Step1)
if err != nil { if err != nil {
logging.Log("SETUP-Hdu8S").WithError(err).Error("unable to create login policy") logging.Log("SETUP-de342").WithField("step", s.step()).WithError(err).Error("unable to finish setup")
return nil, err
}
step.pwComplexityPolicy = new(iam_model.PasswordComplexityPolicyView)
err = step.orgs(ctx, step.Orgs)
if err != nil {
logging.Log("SETUP-p4oWq").WithError(err).Error("unable to set up orgs")
return nil, err
}
ctx = setSetUpContextData(ctx, step.setup.iamID)
err = step.iamOwners(ctx, step.Owners)
if err != nil {
logging.Log("SETUP-WHr01").WithError(err).Error("unable to set up iam owners")
return nil, err
}
err = step.setGlobalOrg(ctx, step.GlobalOrg)
if err != nil {
logging.Log("SETUP-0874m").WithError(err).Error("unable to set global org")
return nil, err
}
err = step.setIamProject(ctx, step.IAMProject)
if err != nil {
logging.Log("SETUP-kaWjq").WithError(err).Error("unable to set zitadel project")
return nil, err
}
iam, err := step.setup.IamEvents.SetupDone(ctx, step.setup.iamID, step.step())
if err != nil {
logging.Log("SETUP-de342").WithField("step", step.step()).WithError(err).Error("unable to finish setup")
return nil, err
}
return iam, nil
}
func (step *Step1) loginPolicy(ctx context.Context, policy LoginPolicy) error {
logging.Log("SETUP-4djul").Info("setting up login policy")
loginPolicy := &iam_model.LoginPolicy{
ObjectRoot: models.ObjectRoot{
AggregateID: step.setup.iamID,
},
AllowRegister: policy.AllowRegister,
AllowUsernamePassword: policy.AllowUsernamePassword,
AllowExternalIdp: policy.AllowExternalIdp,
}
_, err := step.setup.IamEvents.AddLoginPolicy(ctx, loginPolicy)
return err
}
func (step *Step1) orgs(ctx context.Context, orgs []Org) error {
logging.Log("SETUP-dsTh3").Info("setting up orgs")
for _, iamOrg := range orgs {
org, err := step.org(ctx, iamOrg)
if err != nil {
logging.LogWithFields("SETUP-IlLif", "Org", iamOrg.Name).WithError(err).Error("unable to create org")
return err
}
step.createdOrgs[iamOrg.Name] = org
logging.LogWithFields("SETUP-HR2gh", "name", org.Name, "ID", org.AggregateID).Info("created organisation")
var policy *iam_model.OrgIAMPolicyView
if iamOrg.OrgIamPolicy {
policy, err = step.iamorgpolicy(ctx, org)
if err != nil {
logging.LogWithFields("SETUP-IlLif", "Org IAM Policy", iamOrg.Name).WithError(err).Error("unable to create iam org policy")
return err
}
} else {
policy = &iam_model.OrgIAMPolicyView{
UserLoginMustBeDomain: true,
}
}
ctx = setSetUpContextData(ctx, org.AggregateID)
err = step.users(ctx, iamOrg.Users, policy)
if err != nil {
logging.LogWithFields("SETUP-8zfwz", "Org", iamOrg.Name).WithError(err).Error("unable to set up org users")
return err
}
err = step.orgOwners(ctx, org, iamOrg.Owners)
if err != nil {
logging.LogWithFields("SETUP-0874m", "Org", iamOrg.Name).WithError(err).Error("unable to set up org owners")
return err
}
err = step.projects(ctx, iamOrg.Projects, step.createdUsers[iamOrg.Owners[0]].AggregateID)
if err != nil {
logging.LogWithFields("SETUP-wUzqY", "Org", iamOrg.Name).WithError(err).Error("unable to set up org projects")
return err
}
}
logging.Log("SETUP-dgjT4").Info("orgs set up")
return nil
}
func (step *Step1) org(ctx context.Context, org Org) (*org_model.Org, error) {
ctx = setSetUpContextData(ctx, "")
createOrg := &org_model.Org{
Name: org.Name,
Domains: []*org_model.OrgDomain{{Domain: org.Domain}},
}
return step.setup.OrgEvents.CreateOrg(ctx, createOrg, nil)
}
func (step *Step1) iamorgpolicy(ctx context.Context, org *org_model.Org) (*iam_model.OrgIAMPolicyView, error) {
ctx = setSetUpContextData(ctx, org.AggregateID)
policy := &iam_model.OrgIAMPolicy{
ObjectRoot: models.ObjectRoot{AggregateID: org.AggregateID},
UserLoginMustBeDomain: false,
}
createdpolicy, err := step.setup.OrgEvents.AddOrgIAMPolicy(ctx, policy)
if err != nil {
return nil, err
}
return &iam_model.OrgIAMPolicyView{
AggregateID: org.AggregateID,
UserLoginMustBeDomain: createdpolicy.UserLoginMustBeDomain,
}, nil
}
func (step *Step1) iamOwners(ctx context.Context, owners []string) error {
logging.Log("SETUP-dtxfj").Info("setting iam owners")
for _, iamOwner := range owners {
user, ok := step.createdUsers[iamOwner]
if !ok {
logging.LogWithFields("SETUP-8siew", "Owner", iamOwner).Error("unable to add user to iam members")
return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-su6L3", "unable to add user to iam members")
}
_, err := step.setup.IamEvents.AddIAMMember(ctx, &iam_model.IAMMember{ObjectRoot: models.ObjectRoot{AggregateID: step.setup.iamID}, UserID: user.AggregateID, Roles: []string{"IAM_OWNER"}})
if err != nil {
logging.Log("SETUP-LM7rI").WithError(err).Error("unable to add iam administrator to iam members as owner")
return err
}
}
logging.Log("SETUP-fg5aq").Info("iam owners set")
return nil
}
func (step *Step1) setGlobalOrg(ctx context.Context, globalOrgName string) error {
logging.Log("SETUP-dsj75").Info("setting global org")
globalOrg, ok := step.createdOrgs[globalOrgName]
if !ok {
logging.LogWithFields("SETUP-FBhs9", "GlobalOrg", globalOrgName).Error("global org not created")
return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-4GwU7", "global org not created: %v", globalOrgName)
}
if _, err := step.setup.IamEvents.SetGlobalOrg(ctx, step.setup.iamID, globalOrg.AggregateID); err != nil {
logging.Log("SETUP-uGMA3").WithError(err).Error("unable to set global org on iam")
return err return err
} }
logging.Log("SETUP-d32h1").Info("global org set")
return nil return nil
} }
func (step *Step1) setIamProject(ctx context.Context, iamProjectName string) error { //
logging.Log("SETUP-HE3qa").Info("setting iam project") //func (step *Step1) loginPolicy(ctx context.Context, policy LoginPolicy) error {
iamProject, ok := step.createdProjects[iamProjectName] // logging.Log("SETUP-4djul").Info("setting up login policy")
if !ok { // loginPolicy := &iam_model.LoginPolicy{
logging.LogWithFields("SETUP-SJFWP", "IAM Project", iamProjectName).Error("iam project created") // ObjectRoot: models.ObjectRoot{
return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-sGmQt", "iam project not created: %v", iamProjectName) // AggregateID: step.setup.iamID,
} // },
// AllowRegister: policy.AllowRegister,
if _, err := step.setup.IamEvents.SetIAMProject(ctx, step.setup.iamID, iamProject.AggregateID); err != nil { // AllowUsernamePassword: policy.AllowUsernamePassword,
logging.Log("SETUP-i1pNh").WithError(err).Error("unable to set iam project on iam") // AllowExternalIdp: policy.AllowExternalIdp,
return err // }
} // _, err := step.setup.Commands.AddDefaultLoginPolicy(ctx, loginPolicy)
logging.Log("SETUP-d7WEU").Info("iam project set") // return err
return nil //}
} //
//func (step *Step1) orgs(ctx context.Context, orgs []Org) error {
func (step *Step1) users(ctx context.Context, users []User, orgPolicy *iam_model.OrgIAMPolicyView) error { // logging.Log("SETUP-dsTh3").Info("setting up orgs")
for _, user := range users { // for _, iamOrg := range orgs {
created, err := step.user(ctx, user, orgPolicy) // org, err := step.org(ctx, iamOrg)
if err != nil { // if err != nil {
logging.LogWithFields("SETUP-9soer", "Email", user.Email).WithError(err).Error("unable to create iam user") // logging.LogWithFields("SETUP-IlLif", "Org", iamOrg.Name).WithError(err).Error("unable to create org")
return err // return err
} // }
step.createdUsers[user.Email] = created // step.createdOrgs[iamOrg.Name] = org
} // logging.LogWithFields("SETUP-HR2gh", "name", org.Name, "ID", org.AggregateID).Info("created organisation")
return nil //
} // var policy *iam_model.OrgIAMPolicyView
// if iamOrg.OrgIamPolicy {
func (step *Step1) user(ctx context.Context, user User, orgPolicy *iam_model.OrgIAMPolicyView) (*usr_model.User, error) { // policy, err = step.iamorgpolicy(ctx, org)
createUser := &usr_model.User{ // if err != nil {
UserName: user.UserName, // logging.LogWithFields("SETUP-IlLif", "Org IAM Policy", iamOrg.Name).WithError(err).Error("unable to create iam org policy")
Human: &usr_model.Human{ // return err
Profile: &usr_model.Profile{ // }
FirstName: user.FirstName, // } else {
LastName: user.LastName, // policy = &iam_model.OrgIAMPolicyView{
}, // UserLoginMustBeDomain: true,
Email: &usr_model.Email{ // }
EmailAddress: user.Email, // }
IsEmailVerified: true, //
}, // ctx = setSetUpContextData(ctx, org.AggregateID)
Password: &usr_model.Password{ // err = step.users(ctx, iamOrg.Users, policy)
SecretString: user.Password, // if err != nil {
}, // logging.LogWithFields("SETUP-8zfwz", "Org", iamOrg.Name).WithError(err).Error("unable to set up org users")
}, // return err
} // }
return step.setup.UserEvents.CreateUser(ctx, createUser, step.pwComplexityPolicy, orgPolicy) //
} // err = step.orgOwners(ctx, org, iamOrg.Owners)
// if err != nil {
func (step *Step1) orgOwners(ctx context.Context, org *org_model.Org, owners []string) error { // logging.LogWithFields("SETUP-0874m", "Org", iamOrg.Name).WithError(err).Error("unable to set up org owners")
for _, orgOwner := range owners { // return err
user, ok := step.createdUsers[orgOwner] // }
if !ok { //
logging.LogWithFields("SETUP-s9ilr", "Owner", orgOwner).Error("unable to add user to org members") // err = step.projects(ctx, iamOrg.Projects, step.createdUsers[iamOrg.Owners[0]].AggregateID)
return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-s0prs", "unable to add user to org members: %v", orgOwner) // if err != nil {
} // logging.LogWithFields("SETUP-wUzqY", "Org", iamOrg.Name).WithError(err).Error("unable to set up org projects")
err := step.orgOwner(ctx, org, user) // return err
if err != nil { // }
logging.Log("SETUP-s90oe").WithError(err).Error("unable to add global org admin to members of global org") // }
return err // logging.Log("SETUP-dgjT4").Info("orgs set up")
} // return nil
} //}
return nil //
} //func (step *Step1) org(ctx context.Context, org Org) (*org_model.Org, error) {
// ctx = setSetUpContextData(ctx, "")
func (step *Step1) orgOwner(ctx context.Context, org *org_model.Org, user *usr_model.User) error { // createOrg := &org_model.Org{
addMember := &org_model.OrgMember{ // Name: org.Name,
ObjectRoot: models.ObjectRoot{AggregateID: org.AggregateID}, // Domains: []*org_model.OrgDomain{{Domain: org.Domain}},
UserID: user.AggregateID, // }
Roles: []string{OrgOwnerRole}, // return step.setup.OrgEvents.CreateOrg(ctx, createOrg, nil)
} //}
_, err := step.setup.OrgEvents.AddOrgMember(ctx, addMember) //
return err //func (step *Step1) iamorgpolicy(ctx context.Context, org *org_model.Org) (*iam_model.OrgIAMPolicyView, error) {
} // ctx = setSetUpContextData(ctx, org.AggregateID)
// policy := &iam_model.OrgIAMPolicy{
func (step *Step1) projects(ctx context.Context, projects []Project, ownerID string) error { // ObjectRoot: models.ObjectRoot{AggregateID: org.AggregateID},
ctxData := authz.GetCtxData(ctx) // UserLoginMustBeDomain: false,
ctxData.UserID = ownerID // }
projectCtx := authz.SetCtxData(ctx, ctxData) // createdpolicy, err := step.setup.OrgEvents.AddOrgIAMPolicy(ctx, policy)
// if err != nil {
for _, project := range projects { // return nil, err
createdProject, err := step.project(projectCtx, project) // }
if err != nil { // return &iam_model.OrgIAMPolicyView{
return err // AggregateID: org.AggregateID,
} // UserLoginMustBeDomain: createdpolicy.UserLoginMustBeDomain,
step.createdProjects[createdProject.Name] = createdProject // }, nil
for _, oidc := range project.OIDCApps { //}
app, err := step.oidcApp(ctx, createdProject, oidc) //
if err != nil { //func (step *Step1) iamOwners(ctx context.Context, owners []string) error {
return err // logging.Log("SETUP-dtxfj").Info("setting iam owners")
} // for _, iamOwner := range owners {
logging.LogWithFields("SETUP-asd32f", "name", app.Name, "clientID", app.OIDCConfig.ClientID).Info("created OIDC application") // user, ok := step.createdUsers[iamOwner]
} // if !ok {
} // logging.LogWithFields("SETUP-8siew", "Owner", iamOwner).Error("unable to add user to iam members")
return nil // return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-su6L3", "unable to add user to iam members")
} // }
// _, err := step.setup.Commands.AddIAMMember(ctx, &iam_model.IAMMember{ObjectRoot: models.ObjectRoot{AggregateID: step.setup.iamID}, UserID: user.AggregateID, Roles: []string{"IAM_OWNER"}})
func (step *Step1) project(ctx context.Context, project Project) (*proj_model.Project, error) { // if err != nil {
addProject := &proj_model.Project{ // logging.Log("SETUP-LM7rI").WithError(err).Error("unable to add iam administrator to iam members as owner")
Name: project.Name, // return err
} // }
return step.setup.ProjectEvents.CreateProject(ctx, addProject, false) // }
} // logging.Log("SETUP-fg5aq").Info("iam owners set")
// return nil
func (step *Step1) oidcApp(ctx context.Context, project *proj_model.Project, oidc OIDCApp) (*proj_model.Application, error) { //}
addOIDCApp := &proj_model.Application{ //
ObjectRoot: models.ObjectRoot{AggregateID: project.AggregateID}, //func (step *Step1) setGlobalOrg(ctx context.Context, globalOrgName string) error {
Name: oidc.Name, // logging.Log("SETUP-dsj75").Info("setting global org")
OIDCConfig: &proj_model.OIDCConfig{ // globalOrg, ok := step.createdOrgs[globalOrgName]
RedirectUris: oidc.RedirectUris, // if !ok {
ResponseTypes: getOIDCResponseTypes(oidc.ResponseTypes), // logging.LogWithFields("SETUP-FBhs9", "GlobalOrg", globalOrgName).Error("global org not created")
GrantTypes: getOIDCGrantTypes(oidc.GrantTypes), // return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-4GwU7", "global org not created: %v", globalOrgName)
ApplicationType: getOIDCApplicationType(oidc.ApplicationType), // }
AuthMethodType: getOIDCAuthMethod(oidc.AuthMethodType), //
PostLogoutRedirectUris: oidc.PostLogoutRedirectUris, // if _, err := step.setup.IamEvents.SetGlobalOrg(ctx, step.setup.iamID, globalOrg.AggregateID); err != nil {
DevMode: oidc.DevMode, // logging.Log("SETUP-uGMA3").WithError(err).Error("unable to set global org on iam")
}, // return err
} // }
return step.setup.ProjectEvents.AddApplication(ctx, addOIDCApp) // logging.Log("SETUP-d32h1").Info("global org set")
} // return nil
//}
//
//func (step *Step1) setIamProject(ctx context.Context, iamProjectName string) error {
// logging.Log("SETUP-HE3qa").Info("setting iam project")
// iamProject, ok := step.createdProjects[iamProjectName]
// if !ok {
// logging.LogWithFields("SETUP-SJFWP", "IAM Project", iamProjectName).Error("iam project created")
// return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-sGmQt", "iam project not created: %v", iamProjectName)
// }
//
// if _, err := step.setup.IamEvents.SetIAMProject(ctx, step.setup.iamID, iamProject.AggregateID); err != nil {
// logging.Log("SETUP-i1pNh").WithError(err).Error("unable to set iam project on iam")
// return err
// }
// logging.Log("SETUP-d7WEU").Info("iam project set")
// return nil
//}
//
//func (step *Step1) users(ctx context.Context, users []User, orgPolicy *iam_model.OrgIAMPolicyView) error {
// for _, user := range users {
// created, err := step.user(ctx, user, orgPolicy)
// if err != nil {
// logging.LogWithFields("SETUP-9soer", "Email", user.Email).WithError(err).Error("unable to create iam user")
// return err
// }
// step.createdUsers[user.Email] = created
// }
// return nil
//}
//
//func (step *Step1) user(ctx context.Context, user User, orgPolicy *iam_model.OrgIAMPolicyView) (*usr_model.User, error) {
// createUser := &usr_model.User{
// UserName: user.UserName,
// Human: &usr_model.Human{
// Profile: &usr_model.Profile{
// FirstName: user.FirstName,
// LastName: user.LastName,
// },
// Email: &usr_model.Email{
// EmailAddress: user.Email,
// IsEmailVerified: true,
// },
// Password: &usr_model.Password{
// SecretString: user.Password,
// },
// },
// }
// return step.setup.UserEvents.CreateUser(ctx, createUser, step.pwComplexityPolicy, orgPolicy)
//}
//
//func (step *Step1) orgOwners(ctx context.Context, org *org_model.Org, owners []string) error {
// for _, orgOwner := range owners {
// user, ok := step.createdUsers[orgOwner]
// if !ok {
// logging.LogWithFields("SETUP-s9ilr", "Owner", orgOwner).Error("unable to add user to org members")
// return caos_errs.ThrowPreconditionFailedf(nil, "SETUP-s0prs", "unable to add user to org members: %v", orgOwner)
// }
// err := step.orgOwner(ctx, org, user)
// if err != nil {
// logging.Log("SETUP-s90oe").WithError(err).Error("unable to add global org admin to members of global org")
// return err
// }
// }
// return nil
//}
//
//func (step *Step1) orgOwner(ctx context.Context, org *org_model.Org, user *usr_model.User) error {
// addMember := &org_model.OrgMember{
// ObjectRoot: models.ObjectRoot{AggregateID: org.AggregateID},
// UserID: user.AggregateID,
// Roles: []string{OrgOwnerRole},
// }
// _, err := step.setup.OrgEvents.AddOrgMember(ctx, addMember)
// return err
//}
//
//func (step *Step1) projects(ctx context.Context, projects []Project, ownerID string) error {
// ctxData := authz.GetCtxData(ctx)
// ctxData.UserID = ownerID
// projectCtx := authz.SetCtxData(ctx, ctxData)
//
// for _, project := range projects {
// createdProject, err := step.project(projectCtx, project)
// if err != nil {
// return err
// }
// step.createdProjects[createdProject.Name] = createdProject
// for _, oidc := range project.OIDCApps {
// app, err := step.oidcApp(ctx, createdProject, oidc)
// if err != nil {
// return err
// }
// logging.LogWithFields("SETUP-asd32f", "name", app.Name, "clientID", app.OIDCConfig.ClientID).Info("created OIDC application")
// }
// }
// return nil
//}
//
//func (step *Step1) project(ctx context.Context, project Project) (*proj_model.Project, error) {
// addProject := &proj_model.Project{
// Name: project.Name,
// }
// return step.setup.ProjectEvents.CreateProject(ctx, addProject, false)
//}
//
//func (step *Step1) oidcApp(ctx context.Context, project *proj_model.Project, oidc OIDCApp) (*proj_model.Application, error) {
// addOIDCApp := &proj_model.Application{
// ObjectRoot: models.ObjectRoot{AggregateID: project.AggregateID},
// Name: oidc.Name,
// OIDCConfig: &proj_model.OIDCConfig{
// RedirectUris: oidc.RedirectUris,
// ResponseTypes: getOIDCResponseTypes(oidc.ResponseTypes),
// GrantTypes: getOIDCGrantTypes(oidc.GrantTypes),
// ApplicationType: getOIDCApplicationType(oidc.ApplicationType),
// AuthMethodType: getOIDCAuthMethod(oidc.AuthMethodType),
// PostLogoutRedirectUris: oidc.PostLogoutRedirectUris,
// DevMode: oidc.DevMode,
// },
// }
// return step.setup.ProjectEvents.AddApplication(ctx, addOIDCApp)
//}

View File

@ -2,11 +2,13 @@ package setup
import ( import (
"context" "context"
"github.com/caos/logging" "github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/eventstore/models"
es_sdk "github.com/caos/zitadel/internal/eventstore/sdk"
iam_model "github.com/caos/zitadel/internal/iam/model" iam_model "github.com/caos/zitadel/internal/iam/model"
iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model"
"github.com/caos/zitadel/internal/v2/command"
) )
type Step2 struct { type Step2 struct {
@ -27,23 +29,25 @@ func (step *Step2) init(setup *Setup) {
step.setup = setup step.setup = setup
} }
func (step *Step2) execute(ctx context.Context) (*iam_model.IAM, error) { func (step *Step2) execute(ctx context.Context, commands command.CommandSide) error {
iam, agg, err := step.passwordComplexityPolicy(ctx, &step.DefaultPasswordComplexityPolicy) //commands.SetupStep2(ctx, )
if err != nil { //iam, agg, err := step.passwordComplexityPolicy(ctx, &step.DefaultPasswordComplexityPolicy)
logging.Log("SETUP-Ms9fl").WithField("step", step.step()).WithError(err).Error("unable to finish setup (pw complexity policy)") //if err != nil {
return nil, err // logging.Log("SETUP-Ms9fl").WithField("step", step.step()).WithError(err).Error("unable to finish setup (pw complexity policy)")
} // return nil, err
iam, agg, push, err := step.setup.IamEvents.PrepareSetupDone(ctx, iam, agg, step.step()) //}
if err != nil { //iam, agg, push, err := step.setup.IamEvents.PrepareSetupDone(ctx, iam, agg, step.step())
logging.Log("SETUP-V8sui").WithField("step", step.step()).WithError(err).Error("unable to finish setup (prepare setup done)") //if err != nil {
return nil, err // logging.Log("SETUP-V8sui").WithField("step", step.step()).WithError(err).Error("unable to finish setup (prepare setup done)")
} // return nil, err
err = es_sdk.PushAggregates(ctx, push, iam.AppendEvents, agg) //}
if err != nil { //err = es_sdk.PushAggregates(ctx, push, iam.AppendEvents, agg)
logging.Log("SETUP-V8sui").WithField("step", step.step()).WithError(err).Error("unable to finish setup") //if err != nil {
return nil, err // logging.Log("SETUP-V8sui").WithField("step", step.step()).WithError(err).Error("unable to finish setup")
} // return nil, err
return iam_es_model.IAMToModel(iam), nil //}
//return iam_es_model.IAMToModel(iam), nil
return nil
} }
func (step *Step2) passwordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_es_model.IAM, *models.Aggregate, error) { func (step *Step2) passwordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_es_model.IAM, *models.Aggregate, error) {

View File

@ -17,15 +17,21 @@ Errors:
NotLocked: Benutzer ist nicht gesperrt NotLocked: Benutzer ist nicht gesperrt
NoChanges: Keine Änderungen gefunden NoChanges: Keine Änderungen gefunden
InitCodeNotFound: Kein Initialisierungs Code gefunden InitCodeNotFound: Kein Initialisierungs Code gefunden
ProfileNotFound: Profil nicht gefunden Profile:
ProfileInvalid: Profildaten sind ungültig NotFound: Profil nicht gefunden
EmailNotFound: Email nicht gefunden NotChanged: Profile nicht verändert
EmailInvalid: Email ist ungültig Invalid: Profildaten sind ungültig
EmailAlreadyVerified: Email ist bereits verifiziert Email:
NotFound: Email nicht gefunden
Invalid: Email ist ungültig
AlreadyVerified: Email ist bereits verifiziert
NotChanged: Email wurde nicht geändert
PhoneNotFound: Telfonnummer nicht gefunden PhoneNotFound: Telfonnummer nicht gefunden
PhoneInvalid: Telefonnummer ist ungültig PhoneInvalid: Telefonnummer ist ungültig
PhoneAlreadyVerified: Telefonnummer bereits verifiziert PhoneAlreadyVerified: Telefonnummer bereits verifiziert
AddressNotFound: Addresse nicht gefunden Address:
NotFound: Addresse nicht gefunden
NotChanged: Addresse wurde nicht geändert
NotHuman: Der Benutzer muss eine Person sein NotHuman: Der Benutzer muss eine Person sein
NotMachine: Der Benutzer muss technisch sein NotMachine: Der Benutzer muss technisch sein
NotAllowedToLink: Der Benutzer darf nicht mit einem externen Login Provider verlinkt werden NotAllowedToLink: Der Benutzer darf nicht mit einem externen Login Provider verlinkt werden
@ -164,6 +170,8 @@ Errors:
GrantHasNotExistingRole: Eine der Rollen existiert nicht auf dem Projekt GrantHasNotExistingRole: Eine der Rollen existiert nicht auf dem Projekt
UserIDMisisng: User ID fehlt UserIDMisisng: User ID fehlt
IAM: IAM:
Member:
RolesNotChanged: Rollen wurden nicht verändert
MemberInvalid: Member ist ungültig MemberInvalid: Member ist ungültig
MemberAlreadyExisting: Member existiert bereits MemberAlreadyExisting: Member existiert bereits
MemberNotExisting: Member existiert nicht MemberNotExisting: Member existiert nicht
@ -179,6 +187,7 @@ Errors:
IdpProviderInvalid: Idp Provider ist ungültig IdpProviderInvalid: Idp Provider ist ungültig
LoginPolicy: LoginPolicy:
NotFound: Default Login Policy konnte nicht gefunden NotFound: Default Login Policy konnte nicht gefunden
NotChanged: Default Login Policy wurde nicht verändert
NotExisting: Default Login Policy existiert nicht NotExisting: Default Login Policy existiert nicht
AlreadyExists: Default Login Policy existiert bereits AlreadyExists: Default Login Policy existiert bereits
IdpProviderAlreadyExisting: Idp Provider existiert bereits IdpProviderAlreadyExisting: Idp Provider existiert bereits
@ -187,28 +196,41 @@ Errors:
AlreadyExists: Multifaktor existiert bereits AlreadyExists: Multifaktor existiert bereits
NotExisting: Multifaktor existiert nicht NotExisting: Multifaktor existiert nicht
Unspecified: Multifaktor ungültig Unspecified: Multifaktor ungültig
IDP:
AlreadyExists: Identitäts Provider existiert bereits
NotExisting: Identitäts Provider existiert nicht
IDPConfig:
AlreadyExists: Identitäts Provider Konfiguration existiert bereits
NotExisting: Identitäts Provider Konfiguration existiert nicht
NotInactive: Identitäts Provider Konfiguration nicht inaktive
NotActive: Identitäts Provider Konfiguration nicht aktive
LabelPolicy: LabelPolicy:
NotFound: Default Private Label Policy konnte nicht gefunden NotFound: Default Private Label Policy konnte nicht gefunden
NotChanged: Default Private Label Policy wurde nicht verändert
PasswordComplexityPolicy: PasswordComplexityPolicy:
NotFound: Default Password Complexity Policy konnte nicht gefunden werden NotFound: Default Password Complexity Policy konnte nicht gefunden werden
NotExisting: Default Password Complexity Policy existiert nicht NotExisting: Default Password Complexity Policy existiert nicht
AlreadyExists: Default Password Complexity Policy existiert bereits AlreadyExists: Default Password Complexity Policy existiert bereits
Empty: Default Password Complexity Policy leer Empty: Default Password Complexity Policy leer
NotChanged: Default Password Complexity Policy wurde nicht verändert
PasswordAgePolicy: PasswordAgePolicy:
NotFound: Default Password Age Policy konnte nicht gefunden werden NotFound: Default Password Age Policy konnte nicht gefunden werden
NotExisting: Default Password Age Policy existiert nicht NotExisting: Default Password Age Policy existiert nicht
AlreadyExists: Default Password Age Policy existiert bereits AlreadyExists: Default Password Age Policy existiert bereits
Empty: Default Password Age Policy leer Empty: Default Password Age Policy leer
NotChanged: Default Password Age Policy wurde nicht verändert
PasswordLockoutPolicy: PasswordLockoutPolicy:
NotFound: Default Password Lockout Policy konnte nicht gefunden werden NotFound: Default Password Lockout Policy konnte nicht gefunden werden
NotExisting: Default Password Lockout Policy existiert nicht NotExisting: Default Password Lockout Policy existiert nicht
AlreadyExists: Default Password Lockout Policy existiert bereits AlreadyExists: Default Password Lockout Policy existiert bereits
Empty: Default Password Lockout Policy leer Empty: Default Password Lockout Policy leer
NotChanged: Default Password Lockout Policy wurde nicht verändert
OrgIAMPolicy: OrgIAMPolicy:
NotFound: Default Org IAM Policy konnte nicht gefunden werden NotFound: Default Org IAM Policy konnte nicht gefunden werden
NotExisting: Default Org IAM Policy existiert nicht NotExisting: Default Org IAM Policy existiert nicht
AlreadyExists: Default Org IAM Policy existiert bereits AlreadyExists: Default Org IAM Policy existiert bereits
Empty: Default Org IAM Policy leer Empty: Default Org IAM Policy leer
NotChanged: Default Org IAM Policy wurde nicht verändert
Policy: Policy:
AlreadyExists: Policy existiert bereits AlreadyExists: Policy existiert bereits
UserGrant: UserGrant:

View File

@ -17,15 +17,21 @@ Errors:
NotLocked: User is not locked NotLocked: User is not locked
NoChanges: No changes found NoChanges: No changes found
InitCodeNotFound: Initialization Code not found InitCodeNotFound: Initialization Code not found
ProfileNotFound: Profile not found Profile:
ProfileInvalid: Profildata invalid NotFound: Profile not found
EmailNotFound: Email not found NotChanged: Profile not changed
EmailInvalid: Email is invalid Invalid: Profildata invalid
EmailAlreadyVerified: Email is alredy verified Email:
NotFound: Email not found
Invalid: Email is invalid
AlreadyVerified: Email is alredy verified
NotChanged: Email not changed
PhoneNotFound: Phone not found PhoneNotFound: Phone not found
PhoneInvalid: Phone is invalid PhoneInvalid: Phone is invalid
PhoneAlreadyVerified: Phone already verified PhoneAlreadyVerified: Phone already verified
AddressNotFound: Address not found Address:
NotFound: Address not found
NotChanged: Address not changed
NotHuman: The User must be personal NotHuman: The User must be personal
NotMachine: The User must be technical NotMachine: The User must be technical
NotAllowedToLink: User is not allowed to link with external login provider NotAllowedToLink: User is not allowed to link with external login provider
@ -164,6 +170,8 @@ Errors:
GrantHasNotExistingRole: One role doesn't exist on project GrantHasNotExistingRole: One role doesn't exist on project
UserIDMisisng: User ID missing UserIDMisisng: User ID missing
IAM: IAM:
Member:
RolesNotChanged: Roles habe not been changed
MemberInvalid: Member is invalid MemberInvalid: Member is invalid
MemberAlreadyExisting: Member already exists MemberAlreadyExisting: Member already exists
MemberNotExisting: Member does not exist MemberNotExisting: Member does not exist
@ -179,6 +187,7 @@ Errors:
IdpProviderInvalid: Idp Provider is invalid IdpProviderInvalid: Idp Provider is invalid
LoginPolicy: LoginPolicy:
NotFound: Default Login Policy not found NotFound: Default Login Policy not found
NotChanged: Default Login Policy has not been changed
NotExisting: Default Login Policy not existig NotExisting: Default Login Policy not existig
AlreadyExists: Default Login Policy already exists AlreadyExists: Default Login Policy already exists
IdpProviderAlreadyExisting: Idp Provider already existing IdpProviderAlreadyExisting: Idp Provider already existing
@ -187,28 +196,38 @@ Errors:
AlreadyExists: Multifactor already exists AlreadyExists: Multifactor already exists
NotExisting: Multifactor not existing NotExisting: Multifactor not existing
Unspecified: Multifactor invalid Unspecified: Multifactor invalid
IDPConfig:
AlreadyExists: Identity Provider Configuration already exists
NotExisting: Identity Provider Configuration doesn't exist
NotInactive: Identity Provider Configuration not inactive
NotActive: Identity Provider Configuration not active
LabelPolicy: LabelPolicy:
NotFound: Default Private Label Policy not found NotFound: Default Private Label Policy not found
NotChanged: Default Private Label Policy has not been changed
PasswordComplexityPolicy: PasswordComplexityPolicy:
NotFound: Default Private Label Policy not found NotFound: Default Private Label Policy not found
NotExisting: Default Password Complexity Policy not existing NotExisting: Default Password Complexity Policy not existing
AlreadyExists: Default Password Complexity Policy already existing AlreadyExists: Default Password Complexity Policy already existing
Empty: Default Password Complexity Policy empty Empty: Default Password Complexity Policy empty
NotChanged: Default Password Complexity Policy has not been changed
PasswordAgePolicy: PasswordAgePolicy:
NotFound: Default Password Age Policy not found NotFound: Default Password Age Policy not found
NotExisting: Default Password Age Policy not existing NotExisting: Default Password Age Policy not existing
AlreadyExists: Default Password Age Policy already existing AlreadyExists: Default Password Age Policy already existing
Empty: Default Password Age Policy empty Empty: Default Password Age Policy empty
NotChanged: Default Password Age Policy has not been changed
PasswordLockoutPolicy: PasswordLockoutPolicy:
NotFound: Default Password Lockout Policy not found NotFound: Default Password Lockout Policy not found
NotExisting: Default Password Lockout Policy not existing NotExisting: Default Password Lockout Policy not existing
AlreadyExists: Default Password Lockout Policy already existing AlreadyExists: Default Password Lockout Policy already existing
Empty: Default Password Lockout Policy empty Empty: Default Password Lockout Policy empty
NotChanged: Default Password Lockout Policy has not been changed
OrgIAMPolicy: OrgIAMPolicy:
NotFound: Org IAM Policy not found NotFound: Org IAM Policy not found
Empty: Org IAM Policy is empty Empty: Org IAM Policy is empty
NotExisting: Org IAM Policy not existing NotExisting: Org IAM Policy not existing
AlreadyExists: Org IAM Policy already exists AlreadyExists: Org IAM Policy already exists
NotChanged: Org IAM Policy has not been changed
Policy: Policy:
AlreadyExists: Policy already exists AlreadyExists: Policy already exists
UserGrant: UserGrant:

View File

@ -2,6 +2,8 @@ package model
import ( import (
"bytes" "bytes"
caos_errors "github.com/caos/zitadel/internal/errors"
"strings"
"time" "time"
iam_model "github.com/caos/zitadel/internal/iam/model" iam_model "github.com/caos/zitadel/internal/iam/model"
@ -11,6 +13,8 @@ import (
) )
type Human struct { type Human struct {
es_models.ObjectRoot
*Password *Password
*Profile *Profile
*Email *Email
@ -44,6 +48,19 @@ const (
GenderDiverse GenderDiverse
) )
func (u *Human) CheckOrgIAMPolicy(userName string, policy *iam_model.OrgIAMPolicy) error {
if policy == nil {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-zSH7j", "Errors.Users.OrgIamPolicyNil")
}
if policy.UserLoginMustBeDomain && strings.Contains(userName, "@") {
return caos_errors.ThrowPreconditionFailed(nil, "MODEL-se4sJ", "Errors.User.EmailAsUsernameNotAllowed")
}
if !policy.UserLoginMustBeDomain && u.Profile != nil && userName == "" && u.Email != nil {
userName = u.EmailAddress
}
return nil
}
func (u *Human) SetNamesAsDisplayname() { func (u *Human) SetNamesAsDisplayname() {
if u.Profile != nil && u.DisplayName == "" && u.FirstName != "" && u.LastName != "" { if u.Profile != nil && u.DisplayName == "" && u.FirstName != "" && u.LastName != "" {
u.DisplayName = u.FirstName + " " + u.LastName u.DisplayName = u.FirstName + " " + u.LastName

View File

@ -862,13 +862,13 @@ func (es *UserEventstore) ProfileByID(ctx context.Context, userID string) (*usr_
if user.Profile != nil { if user.Profile != nil {
return user.Profile, nil return user.Profile, nil
} }
return nil, caos_errs.ThrowNotFound(nil, "EVENT-dk23f", "Errors.User.ProfileNotFound") return nil, caos_errs.ThrowNotFound(nil, "EVENT-dk23f", "Errors.User.Profile.NotFound")
} }
func (es *UserEventstore) ChangeProfile(ctx context.Context, profile *usr_model.Profile) (*usr_model.Profile, error) { func (es *UserEventstore) ChangeProfile(ctx context.Context, profile *usr_model.Profile) (*usr_model.Profile, error) {
profile.SetNamesAsDisplayname() profile.SetNamesAsDisplayname()
if !profile.IsValid() { if !profile.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-d82i3", "Errors.User.ProfileInvalid") return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-d82i3", "Errors.User.Profile.Invalid")
} }
user, err := es.HumanByID(ctx, profile.AggregateID) user, err := es.HumanByID(ctx, profile.AggregateID)
if err != nil { if err != nil {
@ -897,12 +897,12 @@ func (es *UserEventstore) EmailByID(ctx context.Context, userID string) (*usr_mo
if user.Email != nil { if user.Email != nil {
return user.Email, nil return user.Email, nil
} }
return nil, caos_errs.ThrowNotFound(nil, "EVENT-dki89", "Errors.User.EmailNotFound") return nil, caos_errs.ThrowNotFound(nil, "EVENT-dki89", "Errors.User.Email.NotFound")
} }
func (es *UserEventstore) ChangeEmail(ctx context.Context, email *usr_model.Email) (*usr_model.Email, error) { func (es *UserEventstore) ChangeEmail(ctx context.Context, email *usr_model.Email) (*usr_model.Email, error) {
if !email.IsValid() { if !email.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-lco09", "Errors.User.EmailInvalid") return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-lco09", "Errors.User.Email.Invalid")
} }
user, err := es.HumanByID(ctx, email.AggregateID) user, err := es.HumanByID(ctx, email.AggregateID)
if err != nil { if err != nil {
@ -975,10 +975,10 @@ func (es *UserEventstore) CreateEmailVerificationCode(ctx context.Context, userI
return errors.ThrowPreconditionFailed(nil, "EVENT-E3fbw", "Errors.User.NotInitialised") return errors.ThrowPreconditionFailed(nil, "EVENT-E3fbw", "Errors.User.NotInitialised")
} }
if user.Email == nil { if user.Email == nil {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-pdo9s", "Errors.User.EmailNotFound") return caos_errs.ThrowPreconditionFailed(nil, "EVENT-pdo9s", "Errors.User.Email.NotFound")
} }
if user.IsEmailVerified { if user.IsEmailVerified {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-pdo9s", "Errors.User.EmailAlreadyVerified") return caos_errs.ThrowPreconditionFailed(nil, "EVENT-pdo9s", "Errors.User.Email.AlreadyVerified")
} }
emailCode := new(usr_model.EmailCode) emailCode := new(usr_model.EmailCode)
@ -1158,7 +1158,7 @@ func (es *UserEventstore) AddressByID(ctx context.Context, userID string) (*usr_
if user.Address != nil { if user.Address != nil {
return user.Address, nil return user.Address, nil
} }
return nil, caos_errs.ThrowNotFound(nil, "EVENT-so9wa", "Errors.User.AddressNotFound") return nil, caos_errs.ThrowNotFound(nil, "EVENT-so9wa", "Errors.User.Address.NotFound")
} }
func (es *UserEventstore) ChangeAddress(ctx context.Context, address *usr_model.Address) (*usr_model.Address, error) { func (es *UserEventstore) ChangeAddress(ctx context.Context, address *usr_model.Address) (*usr_model.Address, error) {

View File

@ -1,280 +0,0 @@
package iam
import (
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/repository/iam"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/label"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/login"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/login/idpprovider"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/org_iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_age"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_complexity"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_lockout"
"github.com/caos/zitadel/internal/v2/repository/idp/oidc"
"github.com/caos/zitadel/internal/v2/repository/member"
)
func readModelToIAM(readModel *iam_repo.ReadModel) *model.IAM {
return &model.IAM{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel),
GlobalOrgID: readModel.GlobalOrgID,
IAMProjectID: readModel.ProjectID,
SetUpDone: model.Step(readModel.SetUpDone),
SetUpStarted: model.Step(readModel.SetUpStarted),
Members: readModelToMembers(&readModel.Members),
DefaultLabelPolicy: readModelToLabelPolicy(&readModel.DefaultLabelPolicy),
DefaultLoginPolicy: readModelToLoginPolicy(&readModel.DefaultLoginPolicy),
DefaultOrgIAMPolicy: readModelToOrgIAMPolicy(&readModel.DefaultOrgIAMPolicy),
DefaultPasswordAgePolicy: readModelToPasswordAgePolicy(&readModel.DefaultPasswordAgePolicy),
DefaultPasswordComplexityPolicy: readModelToPasswordComplexityPolicy(&readModel.DefaultPasswordComplexityPolicy),
DefaultPasswordLockoutPolicy: readModelToPasswordLockoutPolicy(&readModel.DefaultPasswordLockoutPolicy),
IDPs: readModelToIDPConfigs(&readModel.IDPs),
}
}
func readModelToMembers(readModel *iam_repo.MembersReadModel) []*model.IAMMember {
members := make([]*model.IAMMember, len(readModel.Members))
for i, member := range readModel.Members {
members[i] = &model.IAMMember{
ObjectRoot: readModelToObjectRoot(member.ReadModel),
Roles: member.Roles,
UserID: member.UserID,
}
}
return members
}
func readModelToLabelPolicy(readModel *label.ReadModel) *model.LabelPolicy {
return &model.LabelPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
PrimaryColor: readModel.PrimaryColor,
SecondaryColor: readModel.SecondaryColor,
Default: true,
//TODO: State: int32,
}
}
func readModelToLoginPolicy(readModel *login.ReadModel) *model.LoginPolicy {
return &model.LoginPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
AllowExternalIdp: readModel.AllowExternalIDP,
AllowRegister: readModel.AllowRegister,
AllowUsernamePassword: readModel.AllowUserNamePassword,
Default: true,
//TODO: IDPProviders: []*model.IDPProvider,
//TODO: State: int32,
}
}
func readModelToOrgIAMPolicy(readModel *org_iam.ReadModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
UserLoginMustBeDomain: readModel.UserLoginMustBeDomain,
Default: true,
//TODO: State: int32,
}
}
func readModelToPasswordAgePolicy(readModel *password_age.ReadModel) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
ExpireWarnDays: uint64(readModel.ExpireWarnDays),
MaxAgeDays: uint64(readModel.MaxAgeDays),
//TODO: State: int32,
}
}
func readModelToPasswordComplexityPolicy(readModel *password_complexity.ReadModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
HasLowercase: readModel.HasLowercase,
HasNumber: readModel.HasNumber,
HasSymbol: readModel.HasSymbol,
HasUppercase: readModel.HasUpperCase,
MinLength: uint64(readModel.MinLength),
//TODO: State: int32,
}
}
func readModelToPasswordLockoutPolicy(readModel *password_lockout.ReadModel) *model.PasswordLockoutPolicy {
return &model.PasswordLockoutPolicy{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel.ReadModel),
MaxAttempts: uint64(readModel.MaxAttempts),
ShowLockOutFailures: readModel.ShowLockOutFailures,
//TODO: State: int32,
}
}
func readModelToObjectRoot(readModel eventstore.ReadModel) models.ObjectRoot {
return models.ObjectRoot{
AggregateID: readModel.AggregateID,
ChangeDate: readModel.ChangeDate,
CreationDate: readModel.CreationDate,
ResourceOwner: readModel.ResourceOwner,
Sequence: readModel.ProcessedSequence,
}
}
func writeModelToObjectRoot(writeModel eventstore.WriteModel) models.ObjectRoot {
return models.ObjectRoot{
AggregateID: writeModel.AggregateID,
ChangeDate: writeModel.ChangeDate,
ResourceOwner: writeModel.ResourceOwner,
Sequence: writeModel.ProcessedSequence,
}
}
func readModelToMember(readModel *member.ReadModel) *model.IAMMember {
return &model.IAMMember{
ObjectRoot: readModelToObjectRoot(readModel.ReadModel),
Roles: readModel.Roles,
UserID: readModel.UserID,
}
}
func writeModelToMember(writeModel *iam.MemberWriteModel) *model.IAMMember {
return &model.IAMMember{
ObjectRoot: writeModelToObjectRoot(writeModel.WriteModel.WriteModel),
Roles: writeModel.Roles,
UserID: writeModel.UserID,
}
}
func writeModelToLoginPolicy(wm *login.WriteModel) *model.LoginPolicy {
return &model.LoginPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
AllowUsernamePassword: wm.AllowUserNamePassword,
AllowRegister: wm.AllowRegister,
AllowExternalIdp: wm.AllowExternalIDP,
ForceMFA: wm.ForceMFA,
PasswordlessType: model.PasswordlessType(wm.PasswordlessType),
}
}
func writeModelToLabelPolicy(wm *label.WriteModel) *model.LabelPolicy {
return &model.LabelPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
PrimaryColor: wm.PrimaryColor,
SecondaryColor: wm.SecondaryColor,
}
}
func writeModelToOrgIAMPolicy(wm *org_iam.WriteModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
UserLoginMustBeDomain: wm.UserLoginMustBeDomain,
}
}
func writeModelToPasswordAgePolicy(wm *password_age.WriteModel) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
MaxAgeDays: wm.MaxAgeDays,
ExpireWarnDays: wm.ExpireWarnDays,
}
}
func writeModelToPasswordComplexityPolicy(wm *password_complexity.WriteModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
MinLength: wm.MinLength,
HasLowercase: wm.HasLowercase,
HasUppercase: wm.HasUpperCase,
HasNumber: wm.HasNumber,
HasSymbol: wm.HasSymbol,
}
}
func writeModelToPasswordLockoutPolicy(wm *password_lockout.WriteModel) *model.PasswordLockoutPolicy {
return &model.PasswordLockoutPolicy{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
MaxAttempts: wm.MaxAttempts,
ShowLockOutFailures: wm.ShowLockOutFailures,
}
}
func readModelToIDPConfigView(rm *iam.IDPConfigReadModel) *model.IDPConfigView {
return &model.IDPConfigView{
AggregateID: rm.AggregateID,
ChangeDate: rm.ChangeDate,
CreationDate: rm.CreationDate,
IDPConfigID: rm.ConfigID,
IDPProviderType: model.IDPProviderType(rm.ProviderType),
IsOIDC: rm.OIDCConfig != nil,
Name: rm.Name,
OIDCClientID: rm.OIDCConfig.ClientID,
OIDCClientSecret: rm.OIDCConfig.ClientSecret,
OIDCIDPDisplayNameMapping: model.OIDCMappingField(rm.OIDCConfig.IDPDisplayNameMapping),
OIDCIssuer: rm.OIDCConfig.Issuer,
OIDCScopes: rm.OIDCConfig.Scopes,
OIDCUsernameMapping: model.OIDCMappingField(rm.OIDCConfig.UserNameMapping),
Sequence: rm.ProcessedSequence,
State: model.IDPConfigState(rm.State),
StylingType: model.IDPStylingType(rm.StylingType),
}
}
func readModelToIDPConfigs(rm *iam.IDPConfigsReadModel) []*model.IDPConfig {
configs := make([]*model.IDPConfig, len(rm.Configs))
for i, config := range rm.Configs {
configs[i] = readModelToIDPConfig(&iam.IDPConfigReadModel{ConfigReadModel: *config})
}
return configs
}
func readModelToIDPConfig(rm *iam.IDPConfigReadModel) *model.IDPConfig {
return &model.IDPConfig{
ObjectRoot: readModelToObjectRoot(rm.ReadModel),
OIDCConfig: readModelToIDPOIDCConfig(rm.OIDCConfig),
IDPConfigID: rm.ConfigID,
Name: rm.Name,
State: model.IDPConfigState(rm.State),
StylingType: model.IDPStylingType(rm.StylingType),
}
}
func readModelToIDPOIDCConfig(rm *oidc.ConfigReadModel) *model.OIDCIDPConfig {
return &model.OIDCIDPConfig{
ObjectRoot: readModelToObjectRoot(rm.ReadModel),
ClientID: rm.ClientID,
ClientSecret: rm.ClientSecret,
ClientSecretString: string(rm.ClientSecret.Crypted),
IDPConfigID: rm.IDPConfigID,
IDPDisplayNameMapping: model.OIDCMappingField(rm.IDPDisplayNameMapping),
Issuer: rm.Issuer,
Scopes: rm.Scopes,
UsernameMapping: model.OIDCMappingField(rm.UserNameMapping),
}
}
func writeModelToIDPConfig(wm *iam.IDPConfigWriteModel) *model.IDPConfig {
return &model.IDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
OIDCConfig: writeModelToIDPOIDCConfig(wm.OIDCConfig),
IDPConfigID: wm.ConfigID,
Name: wm.Name,
State: model.IDPConfigState(wm.State),
StylingType: model.IDPStylingType(wm.StylingType),
}
}
func writeModelToIDPOIDCConfig(wm *oidc.ConfigWriteModel) *model.OIDCIDPConfig {
return &model.OIDCIDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
ClientID: wm.ClientID,
IDPConfigID: wm.IDPConfigID,
IDPDisplayNameMapping: model.OIDCMappingField(wm.IDPDisplayNameMapping),
Issuer: wm.Issuer,
Scopes: wm.Scopes,
UsernameMapping: model.OIDCMappingField(wm.UserNameMapping),
}
}
func writeModelToIDPProvider(wm *idpprovider.WriteModel) *model.IDPProvider {
return &model.IDPProvider{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel.WriteModel),
IDPConfigID: wm.IDPConfigID,
Type: model.IDPProviderType(wm.IDPProviderType),
}
}

View File

@ -1,130 +0,0 @@
package iam
import (
"context"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/idp"
"github.com/caos/zitadel/internal/v2/repository/idp/oidc"
)
func (r *Repository) IDPConfigByID(ctx context.Context, iamID, idpConfigID string) (*iam_model.IDPConfigView, error) {
idpConfig := iam.NewIDPConfigReadModel(iamID, idpConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, idpConfig)
if err != nil {
return nil, err
}
return readModelToIDPConfigView(idpConfig), nil
}
func (r *Repository) AddIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
if config.OIDCConfig == nil {
return nil, errors.ThrowInvalidArgument(nil, "IAM-eUpQU", "Errors.idp.config.notset")
}
idpConfigID, err := r.idGenerator.Next()
if err != nil {
return nil, err
}
//TODO: check name unique on aggregate
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.secretCrypto)
if err != nil {
return nil, err
}
writeModel, err := r.pushIDPWriteModel(ctx, config.AggregateID, idpConfigID, func(a *iam.Aggregate, _ *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.
PushIDPConfigAdded(
ctx,
idpConfigID,
config.Name,
idp.ConfigType(config.Type),
idp.StylingType(config.StylingType)).
PushIDPOIDCConfigAdded(
ctx,
config.OIDCConfig.ClientID,
idpConfigID,
config.OIDCConfig.Issuer,
clientSecret,
oidc.MappingField(config.OIDCConfig.IDPDisplayNameMapping),
oidc.MappingField(config.OIDCConfig.UsernameMapping),
config.OIDCConfig.Scopes...)
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) ChangeIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushIDPWriteModel(ctx, config.AggregateID, config.IDPConfigID, func(a *iam.Aggregate, writeModel *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.PushIDPConfigChanged(
ctx,
writeModel,
config.IDPConfigID,
config.Name,
idp.ConfigType(config.Type),
idp.StylingType(config.StylingType))
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) DeactivateIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushIDPWriteModel(ctx, iamID, idpID, func(a *iam.Aggregate, _ *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.PushIDPConfigDeactivated(ctx, idpID)
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) ReactivateIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushIDPWriteModel(ctx, iamID, idpID, func(a *iam.Aggregate, _ *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.PushIDPConfigReactivated(ctx, idpID)
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) RemoveIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushIDPWriteModel(ctx, iamID, idpID, func(a *iam.Aggregate, _ *iam.IDPConfigWriteModel) *iam.Aggregate {
return a.PushIDPConfigRemoved(ctx, idpID)
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *Repository) pushIDPWriteModel(ctx context.Context, iamID, idpID string, eventSetter func(*iam.Aggregate, *iam.IDPConfigWriteModel) *iam.Aggregate) (*iam.IDPConfigWriteModel, error) {
writeModel := iam.NewIDPConfigWriteModel(iamID, idpID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
aggregate := eventSetter(iam.AggregateFromWriteModel(&writeModel.WriteModel), writeModel)
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,44 +0,0 @@
package iam
import (
"context"
"github.com/caos/zitadel/internal/crypto"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/idp/oidc"
)
func (r *Repository) ChangeIDPOIDCConfig(ctx context.Context, config *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) {
writeModel := iam.NewIDPOIDCConfigWriteModel(config.AggregateID, config.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
var clientSecret *crypto.CryptoValue
if config.ClientSecretString != "" {
clientSecret, err = crypto.Crypt([]byte(config.ClientSecretString), r.secretCrypto)
if err != nil {
return nil, err
}
}
aggregate := iam.AggregateFromWriteModel(&writeModel.WriteModel).
PushIDPOIDCConfigChanged(
ctx,
writeModel,
config.ClientID,
config.Issuer,
clientSecret,
oidc.MappingField(config.IDPDisplayNameMapping),
oidc.MappingField(config.UsernameMapping),
config.Scopes...)
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
if err != nil {
return nil, err
}
return writeModelToIDPOIDCConfig(&writeModel.ConfigWriteModel), nil
}

View File

@ -1,60 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/org_iam"
)
func (r *Repository) AddOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
addedPolicy := org_iam.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.OrgIAMPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToOrgIAMPolicy(addedPolicy), nil
}
func (r *Repository) ChangeOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushOrgIAMPolicyChangedFromExisting(ctx, existingPolicy, policy.UserLoginMustBeDomain)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToOrgIAMPolicy(existingPolicy), nil
}
func (r *Repository) orgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *org_iam.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := org_iam.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,69 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/label"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
func (r *Repository) AddLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mv0s", "Errors.IAM.LabelPolicyInvalid")
}
addedPolicy := label.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushLabelPolicyAddedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLabelPolicy(addedPolicy), nil
}
func (r *Repository) ChangeLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-6M0od", "Errors.IAM.LabelPolicyInvalid")
}
existingPolicy, err := r.labelPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushLabelPolicyChangedFromExisting(ctx, existingPolicy, policy.PrimaryColor, policy.SecondaryColor)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLabelPolicy(existingPolicy), nil
}
func (r *Repository) labelPolicyWriteModelByID(ctx context.Context, iamID string) (policy *label.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := label.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,160 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
iam_login "github.com/caos/zitadel/internal/v2/repository/iam/policy/login"
iam_factor "github.com/caos/zitadel/internal/v2/repository/iam/policy/login/factors"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/login/idpprovider"
"github.com/caos/zitadel/internal/v2/repository/policy/login"
"github.com/caos/zitadel/internal/v2/repository/policy/login/factors"
idpprovider2 "github.com/caos/zitadel/internal/v2/repository/policy/login/idpprovider"
)
func (r *Repository) AddLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mv0s", "Errors.IAM.LoginPolicyInvalid")
}
addedPolicy := iam_login.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushLoginPolicyAddedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, login.PasswordlessType(policy.PasswordlessType))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLoginPolicy(addedPolicy), nil
}
func (r *Repository) ChangeLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-6M0od", "Errors.IAM.LoginPolicyInvalid")
}
existingPolicy, err := r.loginPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushLoginPolicyChangedFromExisting(ctx, existingPolicy, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, login.PasswordlessType(policy.PasswordlessType))
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLoginPolicy(existingPolicy), nil
}
func (r *Repository) AddIDPProviderToLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) {
writeModel := idpprovider.NewWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.WriteModel.WriteModel).
PushLoginPolicyIDPProviderAddedEvent(ctx, idpProvider.IDPConfigID, idpprovider2.Type(idpProvider.Type))
if err = r.eventstore.PushAggregate(ctx, writeModel, aggregate); err != nil {
return nil, err
}
return writeModelToIDPProvider(writeModel), nil
}
func (r *Repository) RemoveIDPProviderFromLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) error {
writeModel := idpprovider.NewWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.WriteModel.WriteModel).
PushLoginPolicyIDPProviderAddedEvent(ctx, idpProvider.IDPConfigID, idpprovider2.Type(idpProvider.Type))
return r.eventstore.PushAggregate(ctx, writeModel, aggregate)
}
func (r *Repository) AddSecondFactorToLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.SecondFactorType) (iam_model.SecondFactorType, error) {
writeModel := iam_factor.NewSecondFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return iam_model.SecondFactorTypeUnspecified, err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.SecondFactorWriteModel.WriteModel).
PushLoginPolicySecondFactorAdded(ctx, factors.SecondFactorType(secondFactor))
if err = r.eventstore.PushAggregate(ctx, writeModel, aggregate); err != nil {
return iam_model.SecondFactorTypeUnspecified, err
}
return iam_model.SecondFactorType(writeModel.MFAType), nil
}
func (r *Repository) RemoveSecondFactorFromLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.SecondFactorType) error {
writeModel := iam_factor.NewSecondFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.SecondFactorWriteModel.WriteModel).
PushLoginPolicySecondFactorRemoved(ctx, factors.SecondFactorType(secondFactor))
return r.eventstore.PushAggregate(ctx, writeModel, aggregate)
}
func (r *Repository) AddMultiFactorToLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.MultiFactorType) (iam_model.MultiFactorType, error) {
writeModel := iam_factor.NewMultiFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return iam_model.MultiFactorTypeUnspecified, err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.MultiFactoryWriteModel.WriteModel).
PushLoginPolicyMultiFactorAdded(ctx, factors.MultiFactorType(secondFactor))
if err = r.eventstore.PushAggregate(ctx, writeModel, aggregate); err != nil {
return iam_model.MultiFactorTypeUnspecified, err
}
return iam_model.MultiFactorType(writeModel.MultiFactoryWriteModel.MFAType), nil
}
func (r *Repository) RemoveMultiFactorFromLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.MultiFactorType) error {
writeModel := iam_factor.NewMultiFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return err
}
aggregate := iam_repo.AggregateFromWriteModel(&writeModel.MultiFactoryWriteModel.WriteModel).
PushLoginPolicyMultiFactorRemoved(ctx, factors.MultiFactorType(secondFactor))
return r.eventstore.PushAggregate(ctx, writeModel, aggregate)
}
func (r *Repository) loginPolicyWriteModelByID(ctx context.Context, iamID string) (policy *iam_login.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := iam_login.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,60 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_age"
)
func (r *Repository) AddPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
addedPolicy := password_age.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-6L0pd", "Errors.IAM.PasswordAgePolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushPasswordAgePolicyAddedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordAgePolicy(addedPolicy), nil
}
func (r *Repository) ChangePasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
existingPolicy, err := r.passwordAgePolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushPasswordAgePolicyChangedFromExisting(ctx, existingPolicy, policy.ExpireWarnDays, policy.MaxAgeDays)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordAgePolicy(existingPolicy), nil
}
func (r *Repository) passwordAgePolicyWriteModelByID(ctx context.Context, iamID string) (policy *password_age.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := password_age.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,68 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_complexity"
)
func (r *Repository) AddPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
if err := policy.IsValid(); err != nil {
return nil, err
}
addedPolicy := password_complexity.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordComplexityPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushPasswordComplexityPolicyAddedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordComplexityPolicy(addedPolicy), nil
}
func (r *Repository) ChangePasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
if err := policy.IsValid(); err != nil {
return nil, err
}
existingPolicy, err := r.passwordComplexityPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushPasswordComplexityPolicyChangedFromExisting(ctx, existingPolicy, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordComplexityPolicy(existingPolicy), nil
}
func (r *Repository) passwordComplexityPolicyWriteModelByID(ctx context.Context, iamID string) (policy *password_complexity.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := password_complexity.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,60 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
"github.com/caos/zitadel/internal/v2/repository/iam/policy/password_lockout"
)
func (r *Repository) AddPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
addedPolicy := password_lockout.NewWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy != nil {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0olDf", "Errors.IAM.PasswordLockoutPolicy.AlreadyExists")
}
iamAgg := iam_repo.AggregateFromWriteModel(&addedPolicy.WriteModel.WriteModel).
PushPasswordLockoutPolicyAddedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures)
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordLockoutPolicy(addedPolicy), nil
}
func (r *Repository) ChangePasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
existingPolicy, err := r.passwordLockoutPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
iamAgg := iam_repo.AggregateFromWriteModel(&existingPolicy.WriteModel.WriteModel).
PushPasswordLockoutPolicyChangedFromExisting(ctx, existingPolicy, policy.MaxAttempts, policy.ShowLockOutFailures)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordLockoutPolicy(existingPolicy), nil
}
func (r *Repository) passwordLockoutPolicyWriteModelByID(ctx context.Context, iamID string) (policy *password_lockout.WriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := password_lockout.NewWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -1,50 +0,0 @@
package iam
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2"
iam_model "github.com/caos/zitadel/internal/iam/model"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *Repository) StartSetup(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
iam, err := r.setup(ctx, iamID, iam_repo.Step(step), iam_repo.NewSetupStepStartedEvent(ctx, iam_repo.Step(step)))
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-zx03n", "Setup start failed")
}
return iam, nil
}
func (r *Repository) SetupDone(ctx context.Context, iamID string, step iam_model.Step) (*iam_model.IAM, error) {
iam, err := r.setup(ctx, iamID, iam_repo.Step(step), iam_repo.NewSetupStepDoneEvent(ctx, iam_repo.Step(step)))
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-zx03n", "Setup start failed")
}
return iam, nil
}
func (r *Repository) setup(ctx context.Context, iamID string, step iam_repo.Step, event eventstore.EventPusher) (*iam_model.IAM, error) {
iam, err := r.iamByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if iam != nil && (iam.SetUpStarted >= iam_repo.Step(step) || iam.SetUpStarted != iam.SetUpDone) {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "setup error")
}
aggregate := iam_repo.AggregateFromReadModel(iam).
PushEvents(event)
events, err := r.eventstore.PushAggregates(ctx, aggregate)
if err != nil {
return nil, err
}
if err = iam.AppendAndReduce(events...); err != nil {
return nil, err
}
return readModelToIAM(iam), nil
}

View File

@ -1,99 +0,0 @@
package org
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
type Repository struct {
eventstore *eventstore.Eventstore
}
type Config struct {
Eventstore *eventstore.Eventstore
}
func StartRepository(config *Config) *Repository {
return &Repository{
eventstore: config.Eventstore,
}
}
func (r *Repository) GetMyOrgIamPolicy(ctx context.Context) (*iam_model.OrgIAMPolicyView, error) {
return nil, nil
}
func (r *Repository) GetLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
return nil, nil
}
func (r *Repository) GetDefaultLoginPolicy(ctx context.Context) (*iam_model.LoginPolicyView, error) {
return nil, nil
}
func (r *Repository) AddLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
return nil, nil
}
func (r *Repository) ChangeLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
return nil, nil
}
func (r *Repository) RemoveLoginPolicy(ctx context.Context) error {
return nil
}
func (r *Repository) SearchIDPProviders(ctx context.Context, request *iam_model.IDPProviderSearchRequest) (*iam_model.IDPProviderSearchResponse, error) {
return nil, nil
}
func (r *Repository) AddIDPProviderToLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) {
return nil, nil
}
func (r *Repository) RemoveIDPProviderFromLoginPolicy(ctx context.Context, provider *iam_model.IDPProvider) error {
return nil
}
func (r *Repository) GetPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) {
return nil, nil
}
func (r *Repository) GetDefaultPasswordComplexityPolicy(ctx context.Context) (*iam_model.PasswordComplexityPolicyView, error) {
return nil, nil
}
func (r *Repository) AddPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
return nil, nil
}
func (r *Repository) ChangePasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
return nil, nil
}
func (r *Repository) RemovePasswordComplexityPolicy(ctx context.Context) error {
return nil
}
func (r *Repository) GetPasswordAgePolicy(ctx context.Context) (*iam_model.PasswordAgePolicyView, error) {
return nil, nil
}
func (r *Repository) GetDefaultPasswordAgePolicy(ctx context.Context) (*iam_model.PasswordAgePolicyView, error) {
return nil, nil
}
func (r *Repository) AddPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
return nil, nil
}
func (r *Repository) ChangePasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
return nil, nil
}
func (r *Repository) RemovePasswordAgePolicy(ctx context.Context) error {
return nil
}
func (r *Repository) GetPasswordLockoutPolicy(ctx context.Context) (*iam_model.PasswordLockoutPolicyView, error) {
return nil, nil
}
func (r *Repository) GetDefaultPasswordLockoutPolicy(ctx context.Context) (*iam_model.PasswordLockoutPolicyView, error) {
return nil, nil
}
func (r *Repository) AddPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
return nil, nil
}
func (r *Repository) ChangePasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
return nil, nil
}
func (r *Repository) RemovePasswordLockoutPolicy(ctx context.Context) error {
return nil
}

View File

@ -0,0 +1,72 @@
package command
import (
"context"
sd "github.com/caos/zitadel/internal/config/systemdefaults"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/id"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
type CommandSide struct {
eventstore *eventstore.Eventstore
idGenerator id.Generator
iamID string
idpConfigSecretCrypto crypto.Crypto
userPasswordAlg crypto.HashAlgorithm
initializeUserCode crypto.Generator
emailVerificationCode crypto.Generator
phoneVerificationCode crypto.Generator
passwordVerificationCode crypto.Generator
machineKeyAlg crypto.EncryptionAlgorithm
machineKeySize int
}
type Config struct {
Eventstore *eventstore.Eventstore
SystemDefaults sd.SystemDefaults
}
func StartCommandSide(config *Config) (repo *CommandSide, err error) {
repo = &CommandSide{
eventstore: config.Eventstore,
idGenerator: id.SonyFlakeGenerator,
iamID: config.SystemDefaults.IamID,
}
iam_repo.RegisterEventMappers(repo.eventstore)
repo.idpConfigSecretCrypto, err = crypto.NewAESCrypto(config.SystemDefaults.IDPConfigVerificationKey)
if err != nil {
return nil, err
}
aesCrypto, err := crypto.NewAESCrypto(config.SystemDefaults.UserVerificationKey)
if err != nil {
return nil, err
}
repo.initializeUserCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.InitializeUserCode, aesCrypto)
repo.emailVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.EmailVerificationCode, aesCrypto)
repo.phoneVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.PhoneVerificationCode, aesCrypto)
repo.passwordVerificationCode = crypto.NewEncryptionGenerator(config.SystemDefaults.SecretGenerators.PasswordVerificationCode, aesCrypto)
repo.userPasswordAlg = crypto.NewBCrypt(config.SystemDefaults.SecretGenerators.PasswordSaltCost)
repo.machineKeyAlg = aesCrypto
repo.machineKeySize = int(config.SystemDefaults.SecretGenerators.MachineKeySize)
return repo, nil
}
func (r *CommandSide) iamByID(ctx context.Context, id string) (_ *IAMWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMriteModel(id)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,118 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/iam/model"
)
func writeModelToObjectRoot(writeModel eventstore.WriteModel) models.ObjectRoot {
return models.ObjectRoot{
AggregateID: writeModel.AggregateID,
ChangeDate: writeModel.ChangeDate,
ResourceOwner: writeModel.ResourceOwner,
Sequence: writeModel.ProcessedSequence,
}
}
func writeModelToIAM(wm *IAMWriteModel) *model.IAM {
return &model.IAM{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
SetUpStarted: wm.SetUpStarted,
SetUpDone: wm.SetUpDone,
GlobalOrgID: wm.GlobalOrgID,
IAMProjectID: wm.ProjectID,
}
}
func writeModelToMember(writeModel *IAMMemberWriteModel) *model.IAMMember {
return &model.IAMMember{
ObjectRoot: writeModelToObjectRoot(writeModel.MemberWriteModel.WriteModel),
Roles: writeModel.Roles,
UserID: writeModel.UserID,
}
}
func writeModelToLoginPolicy(wm *IAMLoginPolicyWriteModel) *model.LoginPolicy {
return &model.LoginPolicy{
ObjectRoot: writeModelToObjectRoot(wm.LoginPolicyWriteModel.WriteModel),
AllowUsernamePassword: wm.AllowUserNamePassword,
AllowRegister: wm.AllowRegister,
AllowExternalIdp: wm.AllowExternalIDP,
ForceMFA: wm.ForceMFA,
PasswordlessType: model.PasswordlessType(wm.PasswordlessType),
}
}
func writeModelToLabelPolicy(wm *IAMLabelPolicyWriteModel) *model.LabelPolicy {
return &model.LabelPolicy{
ObjectRoot: writeModelToObjectRoot(wm.LabelPolicyWriteModel.WriteModel),
PrimaryColor: wm.PrimaryColor,
SecondaryColor: wm.SecondaryColor,
}
}
func writeModelToOrgIAMPolicy(wm *IAMOrgIAMPolicyWriteModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
UserLoginMustBeDomain: wm.UserLoginMustBeDomain,
}
}
func writeModelToPasswordAgePolicy(wm *IAMPasswordAgePolicyWriteModel) *model.PasswordAgePolicy {
return &model.PasswordAgePolicy{
ObjectRoot: writeModelToObjectRoot(wm.PasswordAgePolicyWriteModel.WriteModel),
MaxAgeDays: wm.MaxAgeDays,
ExpireWarnDays: wm.ExpireWarnDays,
}
}
func writeModelToPasswordComplexityPolicy(wm *IAMPasswordComplexityPolicyWriteModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PasswordComplexityPolicyWriteModel.WriteModel),
MinLength: wm.MinLength,
HasLowercase: wm.HasLowercase,
HasUppercase: wm.HasUpperCase,
HasNumber: wm.HasNumber,
HasSymbol: wm.HasSymbol,
}
}
func writeModelToPasswordLockoutPolicy(wm *IAMPasswordLockoutPolicyWriteModel) *model.PasswordLockoutPolicy {
return &model.PasswordLockoutPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PasswordLockoutPolicyWriteModel.WriteModel),
MaxAttempts: wm.MaxAttempts,
ShowLockOutFailures: wm.ShowLockOutFailures,
}
}
func writeModelToIDPConfig(wm *IAMIDPConfigWriteModel) *model.IDPConfig {
return &model.IDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
OIDCConfig: writeModelToIDPOIDCConfig(wm.OIDCConfig),
IDPConfigID: wm.ConfigID,
Name: wm.Name,
State: model.IDPConfigState(wm.State),
StylingType: model.IDPStylingType(wm.StylingType),
}
}
func writeModelToIDPOIDCConfig(wm *OIDCConfigWriteModel) *model.OIDCIDPConfig {
return &model.OIDCIDPConfig{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
ClientID: wm.ClientID,
IDPConfigID: wm.IDPConfigID,
IDPDisplayNameMapping: model.OIDCMappingField(wm.IDPDisplayNameMapping),
Issuer: wm.Issuer,
Scopes: wm.Scopes,
UsernameMapping: model.OIDCMappingField(wm.UserNameMapping),
}
}
func writeModelToIDPProvider(wm *IAMIdentityProviderWriteModel) *model.IDPProvider {
return &model.IDPProvider{
ObjectRoot: writeModelToObjectRoot(wm.IdentityProviderWriteModel.WriteModel),
IDPConfigID: wm.IDPConfigID,
Type: model.IDPProviderType(wm.IDPProviderType),
}
}

View File

@ -0,0 +1,159 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/repository/iam"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
if config.OIDCConfig == nil {
return nil, errors.ThrowInvalidArgument(nil, "IAM-eUpQU", "Errors.idp.config.notset")
}
idpConfigID, err := r.idGenerator.Next()
if err != nil {
return nil, err
}
//TODO: check name unique on aggregate
addedConfig := NewIAMIDPConfigWriteModel(config.AggregateID, idpConfigID)
clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.idpConfigSecretCrypto)
if err != nil {
return nil, err
}
iamAgg := IAMAggregateFromWriteModel(&addedConfig.WriteModel)
iamAgg.PushEvents(
iam_repo.NewIDPConfigAddedEvent(
ctx,
idpConfigID,
config.Name,
domain.IDPConfigType(config.Type),
domain.IDPConfigStylingType(config.StylingType),
),
)
iamAgg.PushEvents(
iam_repo.NewIDPOIDCConfigAddedEvent(
ctx, config.OIDCConfig.ClientID,
idpConfigID,
config.OIDCConfig.Issuer,
clientSecret,
domain.OIDCMappingField(config.OIDCConfig.IDPDisplayNameMapping),
domain.OIDCMappingField(config.OIDCConfig.UsernameMapping),
config.OIDCConfig.Scopes...,
),
)
err = r.eventstore.PushAggregate(ctx, addedConfig, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(addedConfig), nil
}
func (r *CommandSide) ChangeDefaultIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, config.AggregateID, config.IDPConfigID)
if err != nil {
return nil, err
}
if existingIDP.State == domain.IDPConfigStateRemoved || existingIDP.State == domain.IDPConfigStateUnspecified {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotExisting")
}
changedEvent, hasChanged := existingIDP.NewChangedEvent(ctx, config.IDPConfigID, config.Name, domain.IDPConfigStylingType(config.StylingType))
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(existingIDP), nil
}
func (r *CommandSide) DeactivateDefaultIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, iamID, idpID)
if err != nil {
return nil, err
}
if existingIDP.State != domain.IDPConfigStateActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9so", "Errors.IAM.IDPConfig.NotActive")
}
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
iamAgg.PushEvents(iam_repo.NewIDPConfigDeactivatedEvent(ctx, idpID))
err = r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(existingIDP), nil
}
func (r *CommandSide) ReactivateDefaultIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
existingIDP, err := r.iamIDPConfigWriteModelByID(ctx, iamID, idpID)
if err != nil {
return nil, err
}
if existingIDP.State != domain.IDPConfigStateInactive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-5Mo0d", "Errors.IAM.IDPConfig.NotInactive")
}
iamAgg := IAMAggregateFromWriteModel(&existingIDP.WriteModel)
iamAgg.PushEvents(iam_repo.NewIDPConfigReactivatedEvent(ctx, idpID))
err = r.eventstore.PushAggregate(ctx, existingIDP, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPConfig(existingIDP), nil
}
func (r *CommandSide) RemoveDefaultIDPConfig(ctx context.Context, iamID, idpID string) (*iam_model.IDPConfig, error) {
writeModel, err := r.pushDefaultIDPWriteModel(ctx, iamID, idpID, func(a *iam.Aggregate, _ *IAMIDPConfigWriteModel) *iam.Aggregate {
a.Aggregate = *a.PushEvents(iam_repo.NewIDPConfigRemovedEvent(ctx, idpID))
return a
})
if err != nil {
return nil, err
}
return writeModelToIDPConfig(writeModel), nil
}
func (r *CommandSide) pushDefaultIDPWriteModel(ctx context.Context, iamID, idpID string, eventSetter func(*iam.Aggregate, *IAMIDPConfigWriteModel) *iam.Aggregate) (*IAMIDPConfigWriteModel, error) {
writeModel := NewIAMIDPConfigWriteModel(iamID, idpID)
err := r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
aggregate := eventSetter(IAMAggregateFromWriteModel(&writeModel.WriteModel), writeModel)
err = r.eventstore.PushAggregate(ctx, writeModel, aggregate)
if err != nil {
return nil, err
}
return writeModel, nil
}
func (r *CommandSide) iamIDPConfigWriteModelByID(ctx context.Context, iamID, idpID string) (policy *IAMIDPConfigWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMIDPConfigWriteModel(iamID, idpID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,100 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMIDPConfigWriteModel struct {
IDPConfigWriteModel
}
func NewIAMIDPConfigWriteModel(iamID, configID string) *IAMIDPConfigWriteModel {
return &IAMIDPConfigWriteModel{
IDPConfigWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
ConfigID: configID,
},
}
}
func (wm *IAMIDPConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID)
}
func (wm *IAMIDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.IDPConfigAddedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigAddedEvent)
case *iam.IDPConfigChangedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigChangedEvent)
case *iam.IDPConfigDeactivatedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
case *iam.IDPConfigReactivatedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
case *iam.IDPConfigRemovedEvent:
if wm.ConfigID != e.ConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
case *iam.IDPOIDCConfigAddedEvent:
if wm.ConfigID != e.IDPConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
case *iam.IDPOIDCConfigChangedEvent:
if wm.ConfigID != e.IDPConfigID {
continue
}
wm.IDPConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
}
}
}
func (wm *IAMIDPConfigWriteModel) Reduce() error {
return wm.IDPConfigWriteModel.Reduce()
}
func (wm *IAMIDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventReader) error {
wm.AppendEvents(events...)
return wm.Reduce()
}
func (wm *IAMIDPConfigWriteModel) NewChangedEvent(
ctx context.Context,
configID,
name string,
stylingType domain.IDPConfigStylingType,
) (*iam.IDPConfigChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewIDPConfigChangedEvent(ctx)
changedEvent.ConfigID = configID
if wm.Name != name {
hasChanged = true
changedEvent.Name = name
}
if stylingType.Valid() && wm.StylingType != stylingType {
hasChanged = true
changedEvent.StylingType = stylingType
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,47 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/v2/domain"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
func (r *CommandSide) ChangeDefaultIDPOIDCConfig(ctx context.Context, config *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) {
existingConfig := NewIDPOIDCConfigWriteModel(config.AggregateID, config.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, existingConfig)
if err != nil {
return nil, err
}
if existingConfig.State == domain.IDPConfigStateRemoved || existingConfig.State == domain.IDPConfigStateUnspecified {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-67J9d", "Errors.IAM.IDPConfig.AlreadyExists")
}
changedEvent, hasChanged, err := existingConfig.NewChangedEvent(
ctx,
config.ClientID,
config.Issuer,
config.ClientSecretString,
r.idpConfigSecretCrypto,
domain.OIDCMappingField(config.IDPDisplayNameMapping),
domain.OIDCMappingField(config.UsernameMapping),
config.Scopes...)
if err != nil {
return nil, err
}
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingConfig.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingConfig, iamAgg)
if err != nil {
return nil, err
}
return writeModelToIDPOIDCConfig(&existingConfig.OIDCConfigWriteModel), nil
}

View File

@ -0,0 +1,115 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
"reflect"
)
type IDPOIDCConfigWriteModel struct {
OIDCConfigWriteModel
}
func NewIDPOIDCConfigWriteModel(iamID, idpConfigID string) *IDPOIDCConfigWriteModel {
return &IDPOIDCConfigWriteModel{
OIDCConfigWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
IDPConfigID: idpConfigID,
},
}
}
func (wm *IDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.IDPOIDCConfigAddedEvent:
if wm.IDPConfigID != e.IDPConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigAddedEvent)
case *iam.IDPOIDCConfigChangedEvent:
if wm.IDPConfigID != e.IDPConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.OIDCConfigChangedEvent)
case *iam.IDPConfigReactivatedEvent:
if wm.IDPConfigID != e.ConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigReactivatedEvent)
case *iam.IDPConfigDeactivatedEvent:
if wm.IDPConfigID != e.ConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigDeactivatedEvent)
case *iam.IDPConfigRemovedEvent:
if wm.IDPConfigID != e.ConfigID {
continue
}
wm.OIDCConfigWriteModel.AppendEvents(&e.IDPConfigRemovedEvent)
default:
wm.OIDCConfigWriteModel.AppendEvents(e)
}
}
}
func (wm *IDPOIDCConfigWriteModel) Reduce() error {
if err := wm.OIDCConfigWriteModel.Reduce(); err != nil {
return err
}
return wm.WriteModel.Reduce()
}
func (wm *IDPOIDCConfigWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID)
}
func (wm *IDPOIDCConfigWriteModel) NewChangedEvent(
ctx context.Context,
clientID,
issuer,
clientSecretString string,
secretCrypto crypto.Crypto,
idpDisplayNameMapping,
userNameMapping domain.OIDCMappingField,
scopes ...string,
) (*iam.IDPOIDCConfigChangedEvent, bool, error) {
hasChanged := false
changedEvent := iam.NewIDPOIDCConfigChangedEvent(ctx)
var clientSecret *crypto.CryptoValue
var err error
if clientSecretString != "" {
clientSecret, err = crypto.Crypt([]byte(clientSecretString), secretCrypto)
if err != nil {
return nil, false, err
}
changedEvent.ClientSecret = clientSecret
}
if wm.ClientID != clientID {
hasChanged = true
changedEvent.ClientID = clientID
}
if wm.Issuer != issuer {
hasChanged = true
changedEvent.Issuer = issuer
}
if idpDisplayNameMapping.Valid() && wm.IDPDisplayNameMapping != idpDisplayNameMapping {
hasChanged = true
changedEvent.IDPDisplayNameMapping = idpDisplayNameMapping
}
if userNameMapping.Valid() && wm.UserNameMapping != userNameMapping {
hasChanged = true
changedEvent.UserNameMapping = userNameMapping
}
if reflect.DeepEqual(wm.Scopes, scopes) {
hasChanged = true
changedEvent.Scopes = scopes
}
return changedEvent, hasChanged, nil
}

View File

@ -1,7 +1,8 @@
package iam package command
import ( import (
"context" "context"
"reflect"
"github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/errors"
caos_errs "github.com/caos/zitadel/internal/errors" caos_errs "github.com/caos/zitadel/internal/errors"
@ -10,14 +11,14 @@ import (
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam" iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
) )
func (r *Repository) AddMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) { func (r *CommandSide) AddIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
//TODO: check if roles valid //TODO: check if roles valid
if !member.IsValid() { if !member.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-W8m4l", "Errors.IAM.MemberInvalid") return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-W8m4l", "Errors.IAM.MemberInvalid")
} }
addedMember := iam_repo.NewMemberWriteModel(member.AggregateID, member.UserID) addedMember := NewIAMMemberWriteModel(member.AggregateID, member.UserID)
err := r.eventstore.FilterToQueryReducer(ctx, addedMember) err := r.eventstore.FilterToQueryReducer(ctx, addedMember)
if err != nil { if err != nil {
return nil, err return nil, err
@ -26,8 +27,8 @@ func (r *Repository) AddMember(ctx context.Context, member *iam_model.IAMMember)
return nil, errors.ThrowAlreadyExists(nil, "IAM-PtXi1", "Errors.IAM.Member.AlreadyExists") return nil, errors.ThrowAlreadyExists(nil, "IAM-PtXi1", "Errors.IAM.Member.AlreadyExists")
} }
iamAgg := iam_repo.AggregateFromWriteModel(&addedMember.WriteModel.WriteModel). iamAgg := IAMAggregateFromWriteModel(&addedMember.MemberWriteModel.WriteModel)
PushMemberAdded(ctx, member.UserID, member.Roles...) iamAgg.PushEvents(iam_repo.NewMemberAddedEvent(ctx, member.UserID, member.Roles...))
err = r.eventstore.PushAggregate(ctx, addedMember, iamAgg) err = r.eventstore.PushAggregate(ctx, addedMember, iamAgg)
if err != nil { if err != nil {
@ -37,23 +38,26 @@ func (r *Repository) AddMember(ctx context.Context, member *iam_model.IAMMember)
return writeModelToMember(addedMember), nil return writeModelToMember(addedMember), nil
} }
//ChangeMember updates an existing member //ChangeIAMMember updates an existing member
func (r *Repository) ChangeMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) { func (r *CommandSide) ChangeIAMMember(ctx context.Context, member *iam_model.IAMMember) (*iam_model.IAMMember, error) {
//TODO: check if roles valid //TODO: check if roles valid
if !member.IsValid() { if !member.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-LiaZi", "Errors.IAM.MemberInvalid") return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-LiaZi", "Errors.IAM.MemberInvalid")
} }
existingMember, err := r.memberWriteModelByID(ctx, member.AggregateID, member.UserID) existingMember, err := r.iamMemberWriteModelByID(ctx, member.AggregateID, member.UserID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
iam := iam_repo.AggregateFromWriteModel(&existingMember.WriteModel.WriteModel). if reflect.DeepEqual(existingMember.Roles, member.Roles) {
PushMemberChangedFromExisting(ctx, existingMember, member.Roles...) return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-LiaZi", "Errors.IAM.Member.RolesNotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingMember.MemberWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewMemberChangedEvent(ctx, member.UserID, member.Roles...))
events, err := r.eventstore.PushAggregates(ctx, iam) events, err := r.eventstore.PushAggregates(ctx, iamAgg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -66,8 +70,8 @@ func (r *Repository) ChangeMember(ctx context.Context, member *iam_model.IAMMemb
return writeModelToMember(existingMember), nil return writeModelToMember(existingMember), nil
} }
func (r *Repository) RemoveMember(ctx context.Context, member *iam_model.IAMMember) error { func (r *CommandSide) RemoveIAMMember(ctx context.Context, member *iam_model.IAMMember) error {
m, err := r.memberWriteModelByID(ctx, member.AggregateID, member.UserID) m, err := r.iamMemberWriteModelByID(ctx, member.AggregateID, member.UserID)
if err != nil && !errors.IsNotFound(err) { if err != nil && !errors.IsNotFound(err) {
return err return err
} }
@ -75,30 +79,17 @@ func (r *Repository) RemoveMember(ctx context.Context, member *iam_model.IAMMemb
return nil return nil
} }
iamAgg := iam_repo.AggregateFromWriteModel(&m.WriteModel.WriteModel). iamAgg := IAMAggregateFromWriteModel(&m.MemberWriteModel.WriteModel)
PushEvents(iam_repo.NewMemberRemovedEvent(ctx, member.UserID)) iamAgg.PushEvents(iam_repo.NewMemberRemovedEvent(ctx, member.UserID))
return r.eventstore.PushAggregate(ctx, m, iamAgg) return r.eventstore.PushAggregate(ctx, m, iamAgg)
} }
func (r *Repository) MemberByID(ctx context.Context, iamID, userID string) (member *iam_repo.MemberReadModel, err error) { func (r *CommandSide) iamMemberWriteModelByID(ctx context.Context, iamID, userID string) (member *IAMMemberWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx) ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }() defer func() { span.EndWithError(err) }()
member = iam_repo.NewMemberReadModel(iamID, userID) writeModel := NewIAMMemberWriteModel(iamID, userID)
err = r.eventstore.FilterToQueryReducer(ctx, member)
if err != nil {
return nil, err
}
return member, nil
}
func (r *Repository) memberWriteModelByID(ctx context.Context, iamID, userID string) (member *iam_repo.MemberWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := iam_repo.NewMemberWriteModel(iamID, userID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel) err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -0,0 +1,52 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMMemberWriteModel struct {
MemberWriteModel
}
func NewIAMMemberWriteModel(iamID, userID string) *IAMMemberWriteModel {
return &IAMMemberWriteModel{
MemberWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
UserID: userID,
},
}
}
func (wm *IAMMemberWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.MemberAddedEvent:
if e.UserID != wm.MemberWriteModel.UserID {
continue
}
wm.MemberWriteModel.AppendEvents(&e.MemberAddedEvent)
case *iam.MemberChangedEvent:
if e.UserID != wm.MemberWriteModel.UserID {
continue
}
wm.MemberWriteModel.AppendEvents(&e.MemberChangedEvent)
case *iam.MemberRemovedEvent:
if e.UserID != wm.MemberWriteModel.UserID {
continue
}
wm.MemberWriteModel.AppendEvents(&e.MemberRemovedEvent)
}
}
}
func (wm *IAMMemberWriteModel) Reduce() error {
return wm.MemberWriteModel.Reduce()
}
func (wm *IAMMemberWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.MemberWriteModel.AggregateID)
}

View File

@ -0,0 +1,77 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMWriteModel struct {
eventstore.WriteModel
SetUpStarted domain.Step
SetUpDone domain.Step
GlobalOrgID string
ProjectID string
}
func NewIAMriteModel(iamID string) *IAMWriteModel {
return &IAMWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
}
}
func (wm *IAMWriteModel) AppendEvents(events ...eventstore.EventReader) {
wm.WriteModel.AppendEvents(events...)
//for _, event := range events {
// switch e := event.(type) {
// case *iam.LabelPolicyAddedEvent:
// wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyAddedEvent)
// case *iam.LabelPolicyChangedEvent:
// wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyChangedEvent)
// }
//}
}
func (wm *IAMWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *iam.ProjectSetEvent:
wm.ProjectID = e.ProjectID
case *iam.GlobalOrgSetEvent:
wm.GlobalOrgID = e.OrgID
case *iam.SetupStepEvent:
if e.Done {
wm.SetUpDone = e.Step
} else {
wm.SetUpStarted = e.Step
}
}
}
return nil
}
func (wm *IAMWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID)
}
//
//func (wm *IAMLabelPolicyWriteModel) HasChanged(primaryColor, secondaryColor string) bool {
// if primaryColor != "" && wm.PrimaryColor != primaryColor {
// return true
// }
// if secondaryColor != "" && wm.SecondaryColor != secondaryColor {
// return true
// }
// return false
//}
func IAMAggregateFromWriteModel(wm *eventstore.WriteModel) *iam.Aggregate {
return &iam.Aggregate{
Aggregate: *eventstore.AggregateFromWriteModel(wm, iam.AggregateType, iam.AggregateVersion),
}
}

View File

@ -0,0 +1,76 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-5Mv0s", "Errors.IAM.LabelPolicyInvalid")
}
addedPolicy := NewIAMLabelPolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LabelPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.LabelPolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLabelPolicyAddedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLabelPolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeDefaultLabelPolicy(ctx context.Context, policy *iam_model.LabelPolicy) (*iam_model.LabelPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-6M0od", "Errors.IAM.LabelPolicyInvalid")
}
existingPolicy, err := r.defaultLabelPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0K9dq", "Errors.IAM.LabelPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.PrimaryColor, policy.SecondaryColor)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LabelPolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLabelPolicy(existingPolicy), nil
}
func (r *CommandSide) defaultLabelPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMLabelPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMLabelPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,60 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMLabelPolicyWriteModel struct {
LabelPolicyWriteModel
}
func NewIAMLabelPolicyWriteModel(iamID string) *IAMLabelPolicyWriteModel {
return &IAMLabelPolicyWriteModel{
LabelPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMLabelPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.LabelPolicyAddedEvent:
wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyAddedEvent)
case *iam.LabelPolicyChangedEvent:
wm.LabelPolicyWriteModel.AppendEvents(&e.LabelPolicyChangedEvent)
}
}
}
func (wm *IAMLabelPolicyWriteModel) Reduce() error {
return wm.LabelPolicyWriteModel.Reduce()
}
func (wm *IAMLabelPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.LabelPolicyWriteModel.AggregateID)
}
func (wm *IAMLabelPolicyWriteModel) NewChangedEvent(
ctx context.Context,
primaryColor,
secondaryColor string,
) (*iam.LabelPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewLabelPolicyChangedEvent(ctx)
if wm.PrimaryColor != primaryColor {
hasChanged = true
changedEvent.PrimaryColor = primaryColor
}
if wm.SecondaryColor != secondaryColor {
hasChanged = true
changedEvent.SecondaryColor = secondaryColor
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,183 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
addedPolicy := NewIAMLoginPolicyWriteModel(policy.AggregateID)
iamAgg, err := r.addDefaultLoginPolicy(ctx, addedPolicy, policy)
if err != nil {
return nil, err
}
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLoginPolicy(addedPolicy), nil
}
func (r *CommandSide) addDefaultLoginPolicy(ctx context.Context, addedPolicy *IAMLoginPolicyWriteModel, policy *iam_model.LoginPolicy) (*iam_repo.Aggregate, error) {
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.LoginPolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicyAddedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType)))
return iamAgg, nil
}
func (r *CommandSide) ChangeDefaultLoginPolicy(ctx context.Context, policy *iam_model.LoginPolicy) (*iam_model.LoginPolicy, error) {
if !policy.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "IAM-6M0od", "Errors.IAM.LoginPolicyInvalid")
}
existingPolicy, err := r.defaultLoginPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-M0sif", "Errors.IAM.LoginPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.AllowUsernamePassword, policy.AllowRegister, policy.AllowExternalIdp, policy.ForceMFA, domain.PasswordlessType(policy.PasswordlessType))
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToLoginPolicy(existingPolicy), nil
}
func (r *CommandSide) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) (*iam_model.IDPProvider, error) {
idpModel := NewIAMIdentityProviderWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
if err != nil {
return nil, err
}
if idpModel.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.IDP.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&idpModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewIdentityProviderAddedEvent(ctx, idpProvider.IDPConfigID, domain.IdentityProviderType(idpProvider.Type)))
if err = r.eventstore.PushAggregate(ctx, idpModel, iamAgg); err != nil {
return nil, err
}
return writeModelToIDPProvider(idpModel), nil
}
func (r *CommandSide) RemoveIDPProviderFromDefaultLoginPolicy(ctx context.Context, idpProvider *iam_model.IDPProvider) error {
idpModel := NewIAMIdentityProviderWriteModel(idpProvider.AggregateID, idpProvider.IDPConfigID)
err := r.eventstore.FilterToQueryReducer(ctx, idpModel)
if err != nil {
return err
}
if !idpModel.IsActive {
return caos_errs.ThrowAlreadyExists(nil, "IAM-39fjs", "Errors.IAM.LoginPolicy.IDP.NotExisting")
}
iamAgg := IAMAggregateFromWriteModel(&idpModel.IdentityProviderWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewIdentityProviderRemovedEvent(ctx, idpProvider.IDPConfigID))
return r.eventstore.PushAggregate(ctx, idpModel, iamAgg)
}
func (r *CommandSide) AddSecondFactorToDefaultLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.SecondFactorType) (iam_model.SecondFactorType, error) {
secondFactorModel := NewIAMSecondFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel)
if err != nil {
return iam_model.SecondFactorTypeUnspecified, err
}
if secondFactorModel.IsActive {
return iam_model.SecondFactorTypeUnspecified, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicySecondFactorAddedEvent(ctx, domain.SecondFactorType(secondFactor)))
if err = r.eventstore.PushAggregate(ctx, secondFactorModel, iamAgg); err != nil {
return iam_model.SecondFactorTypeUnspecified, err
}
return iam_model.SecondFactorType(secondFactorModel.MFAType), nil
}
func (r *CommandSide) RemoveSecondFactorFromDefaultLoginPolicy(ctx context.Context, iamID string, secondFactor iam_model.SecondFactorType) error {
secondFactorModel := NewIAMSecondFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, secondFactorModel)
if err != nil {
return err
}
if !secondFactorModel.IsActive {
return caos_errs.ThrowAlreadyExists(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.NotExisting")
}
iamAgg := IAMAggregateFromWriteModel(&secondFactorModel.SecondFactorWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicySecondFactorRemovedEvent(ctx, domain.SecondFactorType(secondFactor)))
return r.eventstore.PushAggregate(ctx, secondFactorModel, iamAgg)
}
func (r *CommandSide) AddMultiFactorToDefaultLoginPolicy(ctx context.Context, iamID string, multiFactor iam_model.MultiFactorType) (iam_model.MultiFactorType, error) {
multiFactorModel := NewIAMMultiFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel)
if err != nil {
return iam_model.MultiFactorTypeUnspecified, err
}
if multiFactorModel.IsActive {
return iam_model.MultiFactorTypeUnspecified, caos_errs.ThrowAlreadyExists(nil, "IAM-3M9od", "Errors.IAM.LoginPolicy.MFA.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicyMultiFactorAddedEvent(ctx, domain.MultiFactorType(multiFactor)))
if err = r.eventstore.PushAggregate(ctx, multiFactorModel, iamAgg); err != nil {
return iam_model.MultiFactorTypeUnspecified, err
}
return iam_model.MultiFactorType(multiFactorModel.MultiFactoryWriteModel.MFAType), nil
}
func (r *CommandSide) RemoveMultiFactorFromDefaultLoginPolicy(ctx context.Context, iamID string, multiFactor iam_model.MultiFactorType) error {
multiFactorModel := NewIAMMultiFactorWriteModel(iamID)
err := r.eventstore.FilterToQueryReducer(ctx, multiFactorModel)
if err != nil {
return err
}
if multiFactorModel.IsActive {
return caos_errs.ThrowAlreadyExists(nil, "IAM-3M9df", "Errors.IAM.LoginPolicy.MFA.NotExisting")
}
iamAgg := IAMAggregateFromWriteModel(&multiFactorModel.MultiFactoryWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewLoginPolicyMultiFactorRemovedEvent(ctx, domain.MultiFactorType(multiFactor)))
return r.eventstore.PushAggregate(ctx, multiFactorModel, iamAgg)
}
func (r *CommandSide) defaultLoginPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMLoginPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMLoginPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,70 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMSecondFactorWriteModel struct {
SecondFactorWriteModel
}
func NewIAMSecondFactorWriteModel(iamID string) *IAMSecondFactorWriteModel {
return &IAMSecondFactorWriteModel{
SecondFactorWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMSecondFactorWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.LoginPolicySecondFactorAddedEvent:
wm.WriteModel.AppendEvents(&e.SecondFactorAddedEvent)
}
}
}
func (wm *IAMSecondFactorWriteModel) Reduce() error {
return wm.WriteModel.Reduce()
}
func (wm *IAMSecondFactorWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.WriteModel.AggregateID)
}
type IAMMultiFactorWriteModel struct {
MultiFactoryWriteModel
}
func NewIAMMultiFactorWriteModel(iamID string) *IAMMultiFactorWriteModel {
return &IAMMultiFactorWriteModel{
MultiFactoryWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMMultiFactorWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.LoginPolicyMultiFactorAddedEvent:
wm.WriteModel.AppendEvents(&e.MultiFactorAddedEvent)
}
}
}
func (wm *IAMMultiFactorWriteModel) Reduce() error {
return wm.WriteModel.Reduce()
}
func (wm *IAMMultiFactorWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.WriteModel.AggregateID)
}

View File

@ -0,0 +1,42 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMIdentityProviderWriteModel struct {
IdentityProviderWriteModel
}
func NewIAMIdentityProviderWriteModel(iamID, idpConfigID string) *IAMIdentityProviderWriteModel {
return &IAMIdentityProviderWriteModel{
IdentityProviderWriteModel: IdentityProviderWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
IDPConfigID: idpConfigID,
},
}
}
func (wm *IAMIdentityProviderWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.IdentityProviderAddedEvent:
if e.IDPConfigID != wm.IDPConfigID {
continue
}
wm.IdentityProviderWriteModel.AppendEvents(&e.IdentityProviderAddedEvent)
}
}
}
func (wm *IAMIdentityProviderWriteModel) Reduce() error {
return wm.IdentityProviderWriteModel.Reduce()
}
func (wm *IAMIdentityProviderWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.AggregateID)
}

View File

@ -0,0 +1,80 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMLoginPolicyWriteModel struct {
LoginPolicyWriteModel
}
func NewIAMLoginPolicyWriteModel(iamID string) *IAMLoginPolicyWriteModel {
return &IAMLoginPolicyWriteModel{
LoginPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMLoginPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.LoginPolicyAddedEvent:
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyAddedEvent)
case *iam.LoginPolicyChangedEvent:
wm.LoginPolicyWriteModel.AppendEvents(&e.LoginPolicyChangedEvent)
}
}
}
func (wm *IAMLoginPolicyWriteModel) IsValid() bool {
return wm.AggregateID != ""
}
func (wm *IAMLoginPolicyWriteModel) Reduce() error {
return wm.LoginPolicyWriteModel.Reduce()
}
func (wm *IAMLoginPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.LoginPolicyWriteModel.AggregateID)
}
func (wm *IAMLoginPolicyWriteModel) NewChangedEvent(
ctx context.Context,
allowUsernamePassword,
allowRegister,
allowExternalIDP,
forceMFA bool,
passwordlessType domain.PasswordlessType,
) (*iam.LoginPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewLoginPolicyChangedEvent(ctx)
if wm.AllowUserNamePassword == allowUsernamePassword {
hasChanged = true
changedEvent.AllowUserNamePassword = allowUsernamePassword
}
if wm.AllowRegister == allowRegister {
hasChanged = true
changedEvent.AllowRegister = allowRegister
}
if wm.AllowExternalIDP == allowExternalIDP {
hasChanged = true
changedEvent.AllowExternalIDP = allowExternalIDP
}
if wm.ForceMFA != forceMFA {
hasChanged = true
changedEvent.ForceMFA = forceMFA
}
if passwordlessType.Valid() && wm.PasswordlessType != passwordlessType {
hasChanged = true
changedEvent.PasswordlessType = passwordlessType
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,77 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) GetDefaultOrgIAMPolicy(ctx context.Context, aggregateID string) (*iam_model.OrgIAMPolicy, error) {
policyWriteModel := NewIAMOrgIAMPolicyWriteModel(aggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel)
if err != nil {
return nil, err
}
policy := writeModelToOrgIAMPolicy(policyWriteModel)
policy.Default = true
return policy, nil
}
func (r *CommandSide) AddDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
addedPolicy := NewIAMOrgIAMPolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.OrgIAMPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToOrgIAMPolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeDefaultOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
existingPolicy, err := r.defaultOrgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0Pl0d", "Errors.IAM.OrgIAMPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.UserLoginMustBeDomain)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToOrgIAMPolicy(existingPolicy), nil
}
func (r *CommandSide) defaultOrgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMOrgIAMPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMOrgIAMPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,51 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMOrgIAMPolicyWriteModel struct {
PolicyOrgIAMWriteModel
}
func NewIAMOrgIAMPolicyWriteModel(iamID string) *IAMOrgIAMPolicyWriteModel {
return &IAMOrgIAMPolicyWriteModel{
PolicyOrgIAMWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMOrgIAMPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.OrgIAMPolicyAddedEvent:
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyAddedEvent)
case *iam.OrgIAMPolicyChangedEvent:
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyChangedEvent)
}
}
}
func (wm *IAMOrgIAMPolicyWriteModel) Reduce() error {
return wm.PolicyOrgIAMWriteModel.Reduce()
}
func (wm *IAMOrgIAMPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.PolicyOrgIAMWriteModel.AggregateID)
}
func (wm *IAMOrgIAMPolicyWriteModel) NewChangedEvent(ctx context.Context, userLoginMustBeDomain bool) (*iam.OrgIAMPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewOrgIAMPolicyChangedEvent(ctx)
if wm.UserLoginMustBeDomain != userLoginMustBeDomain {
hasChanged = true
changedEvent.UserLoginMustBeDomain = userLoginMustBeDomain
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,67 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
addedPolicy := NewIAMPasswordAgePolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-2B0ps", "Errors.IAM.PasswordAgePolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.PasswordAgePolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewPasswordAgePolicyAddedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordAgePolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeDefaultPasswordAgePolicy(ctx context.Context, policy *iam_model.PasswordAgePolicy) (*iam_model.PasswordAgePolicy, error) {
existingPolicy, err := r.defaultPasswordAgePolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.ExpireWarnDays, policy.MaxAgeDays)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordAgePolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordAgePolicy(existingPolicy), nil
}
func (r *CommandSide) defaultPasswordAgePolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMPasswordAgePolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMPasswordAgePolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,55 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMPasswordAgePolicyWriteModel struct {
PasswordAgePolicyWriteModel
}
func NewIAMPasswordAgePolicyWriteModel(iamID string) *IAMPasswordAgePolicyWriteModel {
return &IAMPasswordAgePolicyWriteModel{
PasswordAgePolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMPasswordAgePolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.PasswordAgePolicyAddedEvent:
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyAddedEvent)
case *iam.PasswordAgePolicyChangedEvent:
wm.PasswordAgePolicyWriteModel.AppendEvents(&e.PasswordAgePolicyChangedEvent)
}
}
}
func (wm *IAMPasswordAgePolicyWriteModel) Reduce() error {
return wm.PasswordAgePolicyWriteModel.Reduce()
}
func (wm *IAMPasswordAgePolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.PasswordAgePolicyWriteModel.AggregateID)
}
func (wm *IAMPasswordAgePolicyWriteModel) NewChangedEvent(ctx context.Context, expireWarnDays, maxAgeDays uint64) (*iam.PasswordAgePolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewPasswordAgePolicyChangedEvent(ctx)
if wm.ExpireWarnDays != expireWarnDays {
hasChanged = true
changedEvent.ExpireWarnDays = expireWarnDays
}
if wm.MaxAgeDays != maxAgeDays {
hasChanged = true
changedEvent.MaxAgeDays = maxAgeDays
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,94 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) GetDefaultPasswordComplexityPolicy(ctx context.Context, aggregateID string) (*iam_model.PasswordComplexityPolicy, error) {
policyWriteModel := NewIAMPasswordComplexityPolicyWriteModel(aggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, policyWriteModel)
if err != nil {
return nil, err
}
policy := writeModelToPasswordComplexityPolicy(policyWriteModel)
policy.Default = true
return policy, nil
}
func (r *CommandSide) AddDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
addedPolicy := NewIAMPasswordComplexityPolicyWriteModel(policy.AggregateID)
iamAgg, err := r.addDefaultPasswordComplexityPolicy(ctx, addedPolicy, policy)
if err != nil {
return nil, err
}
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordComplexityPolicy(addedPolicy), nil
}
func (r *CommandSide) addDefaultPasswordComplexityPolicy(ctx context.Context, addedPolicy *IAMPasswordComplexityPolicyWriteModel, policy *iam_model.PasswordComplexityPolicy) (*iam_repo.Aggregate, error) {
if err := policy.IsValid(); err != nil {
return nil, err
}
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-Lk0dS", "Errors.IAM.PasswordComplexityPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.PasswordComplexityPolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewPasswordComplexityPolicyAddedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol))
return iamAgg, nil
}
func (r *CommandSide) ChangeDefaultPasswordComplexityPolicy(ctx context.Context, policy *iam_model.PasswordComplexityPolicy) (*iam_model.PasswordComplexityPolicy, error) {
if err := policy.IsValid(); err != nil {
return nil, err
}
existingPolicy, err := r.defaultPasswordComplexityPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordAgePolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MinLength, policy.HasLowercase, policy.HasUppercase, policy.HasNumber, policy.HasSymbol)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.LabelPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordComplexityPolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordComplexityPolicy(existingPolicy), nil
}
func (r *CommandSide) defaultPasswordComplexityPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMPasswordComplexityPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMPasswordComplexityPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,75 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMPasswordComplexityPolicyWriteModel struct {
PasswordComplexityPolicyWriteModel
}
func NewIAMPasswordComplexityPolicyWriteModel(iamID string) *IAMPasswordComplexityPolicyWriteModel {
return &IAMPasswordComplexityPolicyWriteModel{
PasswordComplexityPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMPasswordComplexityPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.PasswordComplexityPolicyAddedEvent:
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent)
case *iam.PasswordComplexityPolicyChangedEvent:
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent)
}
}
}
func (wm *IAMPasswordComplexityPolicyWriteModel) Reduce() error {
return wm.PasswordComplexityPolicyWriteModel.Reduce()
}
func (wm *IAMPasswordComplexityPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.PasswordComplexityPolicyWriteModel.AggregateID)
}
func (wm *IAMPasswordComplexityPolicyWriteModel) NewChangedEvent(
ctx context.Context,
minLength uint64,
hasLowercase,
hasUppercase,
hasNumber,
hasSymbol bool,
) (*iam.PasswordComplexityPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewPasswordComplexityPolicyChangedEvent(ctx)
if wm.MinLength != minLength {
hasChanged = true
changedEvent.MinLength = minLength
}
if wm.HasLowercase != hasLowercase {
hasChanged = true
changedEvent.HasLowercase = hasLowercase
}
if wm.HasUpperCase != hasUppercase {
hasChanged = true
changedEvent.HasUpperCase = hasUppercase
}
if wm.HasNumber != hasNumber {
hasChanged = true
changedEvent.HasNumber = hasNumber
}
if wm.HasSymbol != hasSymbol {
hasChanged = true
changedEvent.HasSymbol = hasSymbol
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,67 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) AddDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
addedPolicy := NewIAMPasswordLockoutPolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0olDf", "Errors.IAM.PasswordLockoutPolicy.AlreadyExists")
}
iamAgg := IAMAggregateFromWriteModel(&addedPolicy.PasswordLockoutPolicyWriteModel.WriteModel)
iamAgg.PushEvents(iam_repo.NewPasswordLockoutPolicyAddedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures))
err = r.eventstore.PushAggregate(ctx, addedPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordLockoutPolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeDefaultPasswordLockoutPolicy(ctx context.Context, policy *iam_model.PasswordLockoutPolicy) (*iam_model.PasswordLockoutPolicy, error) {
existingPolicy, err := r.defaultPasswordLockoutPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-0oPew", "Errors.IAM.PasswordLockoutPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.MaxAttempts, policy.ShowLockOutFailures)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "IAM-4M9vs", "Errors.IAM.PasswordLockoutPolicy.NotChanged")
}
iamAgg := IAMAggregateFromWriteModel(&existingPolicy.PasswordLockoutPolicyWriteModel.WriteModel)
iamAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, iamAgg)
if err != nil {
return nil, err
}
return writeModelToPasswordLockoutPolicy(existingPolicy), nil
}
func (r *CommandSide) defaultPasswordLockoutPolicyWriteModelByID(ctx context.Context, iamID string) (policy *IAMPasswordLockoutPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewIAMPasswordLockoutPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,55 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/iam"
)
type IAMPasswordLockoutPolicyWriteModel struct {
PasswordLockoutPolicyWriteModel
}
func NewIAMPasswordLockoutPolicyWriteModel(iamID string) *IAMPasswordLockoutPolicyWriteModel {
return &IAMPasswordLockoutPolicyWriteModel{
PasswordLockoutPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *IAMPasswordLockoutPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *iam.PasswordLockoutPolicyAddedEvent:
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyAddedEvent)
case *iam.PasswordLockoutPolicyChangedEvent:
wm.PasswordLockoutPolicyWriteModel.AppendEvents(&e.PasswordLockoutPolicyChangedEvent)
}
}
}
func (wm *IAMPasswordLockoutPolicyWriteModel) Reduce() error {
return wm.PasswordLockoutPolicyWriteModel.Reduce()
}
func (wm *IAMPasswordLockoutPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, iam.AggregateType).
AggregateIDs(wm.PasswordLockoutPolicyWriteModel.AggregateID)
}
func (wm *IAMPasswordLockoutPolicyWriteModel) NewChangedEvent(ctx context.Context, maxAttempts uint64, showLockoutFailure bool) (*iam.PasswordLockoutPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := iam.NewPasswordLockoutPolicyChangedEvent(ctx)
if wm.MaxAttempts != maxAttempts {
hasChanged = true
changedEvent.MaxAttempts = maxAttempts
}
if wm.ShowLockOutFailures != showLockoutFailure {
hasChanged = true
changedEvent.ShowLockOutFailures = showLockoutFailure
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,29 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type IdentityProviderWriteModel struct {
eventstore.WriteModel
IDPConfigID string
IDPProviderType domain.IdentityProviderType
IsActive bool
}
func (wm *IdentityProviderWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *policy.IdentityProviderAddedEvent:
wm.IDPConfigID = e.IDPConfigID
wm.IDPProviderType = e.IDPProviderType
wm.IsActive = true
case *policy.IdentityProviderRemovedEvent:
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()
}

View File

@ -0,0 +1,75 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
)
type IDPConfigWriteModel struct {
eventstore.WriteModel
State domain.IDPConfigState
ConfigID string
Name string
StylingType domain.IDPConfigStylingType
OIDCConfig *OIDCConfigWriteModel
}
func (rm *IDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) {
rm.WriteModel.AppendEvents(events...)
for _, event := range events {
switch event.(type) {
case *idpconfig.OIDCConfigAddedEvent:
rm.OIDCConfig = new(OIDCConfigWriteModel)
rm.OIDCConfig.AppendEvents(event)
case *idpconfig.OIDCConfigChangedEvent:
rm.OIDCConfig.AppendEvents(event)
}
}
}
func (rm *IDPConfigWriteModel) Reduce() error {
for _, event := range rm.Events {
switch e := event.(type) {
case *idpconfig.IDPConfigAddedEvent:
rm.reduceConfigAddedEvent(e)
case *idpconfig.IDPConfigChangedEvent:
rm.reduceConfigChangedEvent(e)
case *idpconfig.IDPConfigDeactivatedEvent:
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateInactive)
case *idpconfig.IDPConfigReactivatedEvent:
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateActive)
case *idpconfig.IDPConfigRemovedEvent:
rm.reduceConfigStateChanged(e.ConfigID, domain.IDPConfigStateRemoved)
}
}
if rm.OIDCConfig != nil {
if err := rm.OIDCConfig.Reduce(); err != nil {
return err
}
}
return rm.WriteModel.Reduce()
}
func (rm *IDPConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.IDPConfigAddedEvent) {
rm.ConfigID = e.ConfigID
rm.Name = e.Name
rm.StylingType = e.StylingType
rm.State = domain.IDPConfigStateActive
}
func (rm *IDPConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.IDPConfigChangedEvent) {
if e.Name != "" {
rm.Name = e.Name
}
if e.StylingType.Valid() {
rm.StylingType = e.StylingType
}
}
func (rm *IDPConfigWriteModel) reduceConfigStateChanged(configID string, state domain.IDPConfigState) {
rm.State = state
}

View File

@ -0,0 +1,37 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/member"
)
type MemberWriteModel struct {
eventstore.WriteModel
UserID string
Roles []string
IsActive bool
}
func NewMemberWriteModel(userID string) *MemberWriteModel {
return &MemberWriteModel{
UserID: userID,
}
}
func (wm *MemberWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *member.MemberAddedEvent:
wm.UserID = e.UserID
wm.Roles = e.Roles
wm.IsActive = true
case *member.MemberChangedEvent:
wm.Roles = e.Roles
case *member.MemberRemovedEvent:
wm.Roles = nil
wm.IsActive = false
}
}
return wm.WriteModel.Reduce()
}

View File

@ -1,11 +1,13 @@
package oidc package command
import ( import (
"github.com/caos/zitadel/internal/crypto" "github.com/caos/zitadel/internal/crypto"
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/idpconfig"
) )
type ConfigWriteModel struct { type OIDCConfigWriteModel struct {
eventstore.WriteModel eventstore.WriteModel
IDPConfigID string IDPConfigID string
@ -14,24 +16,31 @@ type ConfigWriteModel struct {
Issuer string Issuer string
Scopes []string Scopes []string
IDPDisplayNameMapping MappingField IDPDisplayNameMapping domain.OIDCMappingField
UserNameMapping MappingField UserNameMapping domain.OIDCMappingField
State domain.IDPConfigState
} }
func (wm *ConfigWriteModel) Reduce() error { func (wm *OIDCConfigWriteModel) Reduce() error {
for _, event := range wm.Events { for _, event := range wm.Events {
switch e := event.(type) { switch e := event.(type) {
case *ConfigAddedEvent: case *idpconfig.OIDCConfigAddedEvent:
wm.reduceConfigAddedEvent(e) wm.reduceConfigAddedEvent(e)
case *ConfigChangedEvent: case *idpconfig.OIDCConfigChangedEvent:
wm.reduceConfigChangedEvent(e) wm.reduceConfigChangedEvent(e)
case *idpconfig.IDPConfigDeactivatedEvent:
wm.State = domain.IDPConfigStateInactive
case *idpconfig.IDPConfigReactivatedEvent:
wm.State = domain.IDPConfigStateActive
case *idpconfig.IDPConfigRemovedEvent:
wm.State = domain.IDPConfigStateRemoved
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()
} }
func (wm *ConfigWriteModel) reduceConfigAddedEvent(e *ConfigAddedEvent) { func (wm *OIDCConfigWriteModel) reduceConfigAddedEvent(e *idpconfig.OIDCConfigAddedEvent) {
wm.IDPConfigID = e.IDPConfigID wm.IDPConfigID = e.IDPConfigID
wm.ClientID = e.ClientID wm.ClientID = e.ClientID
wm.ClientSecret = e.ClientSecret wm.ClientSecret = e.ClientSecret
@ -39,9 +48,10 @@ func (wm *ConfigWriteModel) reduceConfigAddedEvent(e *ConfigAddedEvent) {
wm.Scopes = e.Scopes wm.Scopes = e.Scopes
wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping
wm.UserNameMapping = e.UserNameMapping wm.UserNameMapping = e.UserNameMapping
wm.State = domain.IDPConfigStateActive
} }
func (wm *ConfigWriteModel) reduceConfigChangedEvent(e *ConfigChangedEvent) { func (wm *OIDCConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.OIDCConfigChangedEvent) {
if e.ClientID != "" { if e.ClientID != "" {
wm.ClientID = e.ClientID wm.ClientID = e.ClientID
} }

View File

@ -0,0 +1,23 @@
package command
import (
"github.com/caos/zitadel/internal/iam/model"
)
func orgWriteModelToOrgIAMPolicy(wm *ORGOrgIAMPolicyWriteModel) *model.OrgIAMPolicy {
return &model.OrgIAMPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PolicyOrgIAMWriteModel.WriteModel),
UserLoginMustBeDomain: wm.UserLoginMustBeDomain,
}
}
func orgWriteModelToPasswordComplexityPolicy(wm *OrgPasswordComplexityPolicyWriteModel) *model.PasswordComplexityPolicy {
return &model.PasswordComplexityPolicy{
ObjectRoot: writeModelToObjectRoot(wm.PasswordComplexityPolicyWriteModel.WriteModel),
MinLength: wm.MinLength,
HasLowercase: wm.HasLowercase,
HasUppercase: wm.HasUpperCase,
HasNumber: wm.HasNumber,
HasSymbol: wm.HasSymbol,
}
}

View File

@ -0,0 +1,5 @@
package command
type OrgMemberWriteModel struct {
MemberWriteModel
}

View File

@ -0,0 +1,12 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/org"
)
func ORGAggregateFromWriteModel(wm *eventstore.WriteModel) *org.Aggregate {
return &org.Aggregate{
Aggregate: *eventstore.AggregateFromWriteModel(wm, org.AggregateType, org.AggregateVersion),
}
}

View File

@ -0,0 +1,78 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/telemetry/tracing"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) GetOrgIAMPolicy(ctx context.Context, orgID string) (*iam_model.OrgIAMPolicy, error) {
policy := NewORGOrgIAMPolicyWriteModel(orgID)
err := r.eventstore.FilterToQueryReducer(ctx, policy)
if err != nil {
return nil, err
}
if policy.IsActive {
return orgWriteModelToOrgIAMPolicy(policy), nil
}
return r.GetDefaultOrgIAMPolicy(ctx, r.iamID)
}
func (r *CommandSide) AddOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
addedPolicy := NewORGOrgIAMPolicyWriteModel(policy.AggregateID)
err := r.eventstore.FilterToQueryReducer(ctx, addedPolicy)
if err != nil {
return nil, err
}
if addedPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-5M0ds", "Errors.Org.OrgIAMPolicy.AlreadyExists")
}
orgAgg := ORGAggregateFromWriteModel(&addedPolicy.PolicyOrgIAMWriteModel.WriteModel)
orgAgg.PushEvents(iam_repo.NewOrgIAMPolicyAddedEvent(ctx, policy.UserLoginMustBeDomain))
err = r.eventstore.PushAggregate(ctx, addedPolicy, orgAgg)
if err != nil {
return nil, err
}
return orgWriteModelToOrgIAMPolicy(addedPolicy), nil
}
func (r *CommandSide) ChangeOrgIAMPolicy(ctx context.Context, policy *iam_model.OrgIAMPolicy) (*iam_model.OrgIAMPolicy, error) {
existingPolicy, err := r.orgIAMPolicyWriteModelByID(ctx, policy.AggregateID)
if err != nil {
return nil, err
}
if !existingPolicy.IsActive {
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-2N9sd", "Errors.Org.OrgIAMPolicy.NotFound")
}
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx, policy.UserLoginMustBeDomain)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "ORG-3M9ds", "Errors.Org.LabelPolicy.NotChanged")
}
orgAgg := ORGAggregateFromWriteModel(&existingPolicy.PolicyOrgIAMWriteModel.WriteModel)
orgAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingPolicy, orgAgg)
if err != nil {
return nil, err
}
return orgWriteModelToOrgIAMPolicy(existingPolicy), nil
}
func (r *CommandSide) orgIAMPolicyWriteModelByID(ctx context.Context, iamID string) (policy *ORGOrgIAMPolicyWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel := NewORGOrgIAMPolicyWriteModel(iamID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,51 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/org"
)
type ORGOrgIAMPolicyWriteModel struct {
PolicyOrgIAMWriteModel
}
func NewORGOrgIAMPolicyWriteModel(orgID string) *ORGOrgIAMPolicyWriteModel {
return &ORGOrgIAMPolicyWriteModel{
PolicyOrgIAMWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: orgID,
},
},
}
}
func (wm *ORGOrgIAMPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *org.OrgIAMPolicyAddedEvent:
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyAddedEvent)
case *org.OrgIAMPolicyChangedEvent:
wm.PolicyOrgIAMWriteModel.AppendEvents(&e.OrgIAMPolicyChangedEvent)
}
}
}
func (wm *ORGOrgIAMPolicyWriteModel) Reduce() error {
return wm.PolicyOrgIAMWriteModel.Reduce()
}
func (wm *ORGOrgIAMPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
AggregateIDs(wm.PolicyOrgIAMWriteModel.AggregateID)
}
func (wm *ORGOrgIAMPolicyWriteModel) NewChangedEvent(ctx context.Context, userLoginMustBeDomain bool) (*org.OrgIAMPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := org.NewOrgIAMPolicyChangedEvent(ctx)
if wm.UserLoginMustBeDomain != userLoginMustBeDomain {
hasChanged = true
changedEvent.UserLoginMustBeDomain = userLoginMustBeDomain
}
return changedEvent, hasChanged
}

View File

@ -0,0 +1,18 @@
package command
import (
"context"
iam_model "github.com/caos/zitadel/internal/iam/model"
)
func (r *CommandSide) GetOrgPasswordComplexityPolicy(ctx context.Context, orgID string) (*iam_model.PasswordComplexityPolicy, error) {
policy := NewOrgPasswordComplexityPolicyWriteModel(orgID)
err := r.eventstore.FilterToQueryReducer(ctx, policy)
if err != nil {
return nil, err
}
if policy.IsActive {
return orgWriteModelToPasswordComplexityPolicy(policy), nil
}
return r.GetDefaultPasswordComplexityPolicy(ctx, r.iamID)
}

View File

@ -0,0 +1,75 @@
package command
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/org"
)
type OrgPasswordComplexityPolicyWriteModel struct {
PasswordComplexityPolicyWriteModel
}
func NewOrgPasswordComplexityPolicyWriteModel(iamID string) *OrgPasswordComplexityPolicyWriteModel {
return &OrgPasswordComplexityPolicyWriteModel{
PasswordComplexityPolicyWriteModel{
WriteModel: eventstore.WriteModel{
AggregateID: iamID,
},
},
}
}
func (wm *OrgPasswordComplexityPolicyWriteModel) AppendEvents(events ...eventstore.EventReader) {
for _, event := range events {
switch e := event.(type) {
case *org.PasswordComplexityPolicyAddedEvent:
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyAddedEvent)
case *org.PasswordComplexityPolicyChangedEvent:
wm.PasswordComplexityPolicyWriteModel.AppendEvents(&e.PasswordComplexityPolicyChangedEvent)
}
}
}
func (wm *OrgPasswordComplexityPolicyWriteModel) Reduce() error {
return wm.PasswordComplexityPolicyWriteModel.Reduce()
}
func (wm *OrgPasswordComplexityPolicyWriteModel) Query() *eventstore.SearchQueryBuilder {
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent, org.AggregateType).
AggregateIDs(wm.PasswordComplexityPolicyWriteModel.AggregateID)
}
func (wm *OrgPasswordComplexityPolicyWriteModel) NewChangedEvent(
ctx context.Context,
minLength uint64,
hasLowercase,
hasUppercase,
hasNumber,
hasSymbol bool,
) (*org.PasswordComplexityPolicyChangedEvent, bool) {
hasChanged := false
changedEvent := org.NewPasswordComplexityPolicyChangedEvent(ctx)
if wm.MinLength != minLength {
hasChanged = true
changedEvent.MinLength = minLength
}
if wm.HasLowercase != hasLowercase {
hasChanged = true
changedEvent.HasLowercase = hasLowercase
}
if wm.HasUpperCase != hasUppercase {
hasChanged = true
changedEvent.HasUpperCase = hasUppercase
}
if wm.HasNumber != hasNumber {
hasChanged = true
changedEvent.HasNumber = hasNumber
}
if wm.HasSymbol != hasSymbol {
hasChanged = true
changedEvent.HasSymbol = hasSymbol
}
return changedEvent, hasChanged
}

View File

@ -1,25 +1,30 @@
package label package command
import ( import (
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
) )
type WriteModel struct { type LabelPolicyWriteModel struct {
eventstore.WriteModel eventstore.WriteModel
PrimaryColor string PrimaryColor string
SecondaryColor string SecondaryColor string
IsActive bool
} }
func (wm *WriteModel) Reduce() error { func (wm *LabelPolicyWriteModel) Reduce() error {
for _, event := range wm.Events { for _, event := range wm.Events {
switch e := event.(type) { switch e := event.(type) {
case *AddedEvent: case *policy.LabelPolicyAddedEvent:
wm.PrimaryColor = e.PrimaryColor wm.PrimaryColor = e.PrimaryColor
wm.SecondaryColor = e.SecondaryColor wm.SecondaryColor = e.SecondaryColor
case *ChangedEvent: wm.IsActive = true
case *policy.LabelPolicyChangedEvent:
wm.PrimaryColor = e.PrimaryColor wm.PrimaryColor = e.PrimaryColor
wm.SecondaryColor = e.SecondaryColor wm.SecondaryColor = e.SecondaryColor
case *policy.LabelPolicyRemovedEvent:
wm.IsActive = false
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()

View File

@ -1,19 +1,26 @@
package factors package command
import "github.com/caos/zitadel/internal/eventstore/v2" import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type SecondFactorWriteModel struct { type SecondFactorWriteModel struct {
eventstore.WriteModel eventstore.WriteModel
MFAType SecondFactorType MFAType domain.SecondFactorType
IsActive bool
} }
func (wm *SecondFactorWriteModel) Reduce() error { func (wm *SecondFactorWriteModel) Reduce() error {
for _, event := range wm.Events { for _, event := range wm.Events {
switch e := event.(type) { switch e := event.(type) {
case *SecondFactorAddedEvent: case *policy.SecondFactorAddedEvent:
wm.MFAType = e.MFAType wm.MFAType = e.MFAType
case *SecondFactorRemovedEvent: wm.IsActive = true
case *policy.SecondFactorRemovedEvent:
wm.MFAType = e.MFAType wm.MFAType = e.MFAType
wm.IsActive = false
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()
@ -21,16 +28,19 @@ func (wm *SecondFactorWriteModel) Reduce() error {
type MultiFactoryWriteModel struct { type MultiFactoryWriteModel struct {
eventstore.WriteModel eventstore.WriteModel
MFAType MultiFactorType MFAType domain.MultiFactorType
IsActive bool
} }
func (wm *MultiFactoryWriteModel) Reduce() error { func (wm *MultiFactoryWriteModel) Reduce() error {
for _, event := range wm.Events { for _, event := range wm.Events {
switch e := event.(type) { switch e := event.(type) {
case *MultiFactorAddedEvent: case *policy.MultiFactorAddedEvent:
wm.MFAType = e.MFAType wm.MFAType = e.MFAType
case *MultiFactorRemovedEvent: wm.IsActive = true
case *policy.MultiFactorRemovedEvent:
wm.MFAType = e.MFAType wm.MFAType = e.MFAType
wm.IsActive = false
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()

View File

@ -1,34 +1,40 @@
package login package command
import ( import (
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/policy"
) )
type WriteModel struct { type LoginPolicyWriteModel struct {
eventstore.WriteModel eventstore.WriteModel
AllowUserNamePassword bool AllowUserNamePassword bool
AllowRegister bool AllowRegister bool
AllowExternalIDP bool AllowExternalIDP bool
ForceMFA bool ForceMFA bool
PasswordlessType PasswordlessType PasswordlessType domain.PasswordlessType
IsActive bool
} }
func (wm *WriteModel) Reduce() error { func (wm *LoginPolicyWriteModel) Reduce() error {
for _, event := range wm.Events { for _, event := range wm.Events {
switch e := event.(type) { switch e := event.(type) {
case *AddedEvent: case *policy.LoginPolicyAddedEvent:
wm.AllowRegister = e.AllowRegister wm.AllowRegister = e.AllowRegister
wm.AllowUserNamePassword = e.AllowUserNamePassword wm.AllowUserNamePassword = e.AllowUserNamePassword
wm.AllowExternalIDP = e.AllowExternalIDP wm.AllowExternalIDP = e.AllowExternalIDP
wm.ForceMFA = e.ForceMFA wm.ForceMFA = e.ForceMFA
wm.PasswordlessType = e.PasswordlessType wm.PasswordlessType = e.PasswordlessType
case *ChangedEvent: wm.IsActive = true
case *policy.LoginPolicyChangedEvent:
wm.AllowRegister = e.AllowRegister wm.AllowRegister = e.AllowRegister
wm.AllowUserNamePassword = e.AllowUserNamePassword wm.AllowUserNamePassword = e.AllowUserNamePassword
wm.AllowExternalIDP = e.AllowExternalIDP wm.AllowExternalIDP = e.AllowExternalIDP
wm.ForceMFA = e.ForceMFA wm.ForceMFA = e.ForceMFA
wm.PasswordlessType = e.PasswordlessType wm.PasswordlessType = e.PasswordlessType
case *policy.LoginPolicyRemovedEvent:
wm.IsActive = false
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()

View File

@ -0,0 +1,26 @@
package command
import (
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
)
type PolicyOrgIAMWriteModel struct {
eventstore.WriteModel
UserLoginMustBeDomain bool
IsActive bool
}
func (wm *PolicyOrgIAMWriteModel) Reduce() error {
for _, event := range wm.Events {
switch e := event.(type) {
case *policy.OrgIAMPolicyAddedEvent:
wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain
wm.IsActive = true
case *policy.OrgIAMPolicyChangedEvent:
wm.UserLoginMustBeDomain = e.UserLoginMustBeDomain
}
}
return wm.WriteModel.Reduce()
}

View File

@ -1,25 +1,30 @@
package password_age package command
import ( import (
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
) )
type WriteModel struct { type PasswordAgePolicyWriteModel struct {
eventstore.WriteModel eventstore.WriteModel
ExpireWarnDays uint64 ExpireWarnDays uint64
MaxAgeDays uint64 MaxAgeDays uint64
IsActive bool
} }
func (wm *WriteModel) Reduce() error { func (wm *PasswordAgePolicyWriteModel) Reduce() error {
for _, event := range wm.Events { for _, event := range wm.Events {
switch e := event.(type) { switch e := event.(type) {
case *AddedEvent: case *policy.PasswordAgePolicyAddedEvent:
wm.ExpireWarnDays = e.ExpireWarnDays wm.ExpireWarnDays = e.ExpireWarnDays
wm.MaxAgeDays = e.MaxAgeDays wm.MaxAgeDays = e.MaxAgeDays
case *ChangedEvent: wm.IsActive = true
case *policy.PasswordAgePolicyChangedEvent:
wm.ExpireWarnDays = e.ExpireWarnDays wm.ExpireWarnDays = e.ExpireWarnDays
wm.MaxAgeDays = e.MaxAgeDays wm.MaxAgeDays = e.MaxAgeDays
case *policy.PasswordAgePolicyRemovedEvent:
wm.IsActive = false
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()

View File

@ -1,10 +1,11 @@
package password_complexity package command
import ( import (
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
) )
type WriteModel struct { type PasswordComplexityPolicyWriteModel struct {
eventstore.WriteModel eventstore.WriteModel
MinLength uint64 MinLength uint64
@ -12,23 +13,27 @@ type WriteModel struct {
HasUpperCase bool HasUpperCase bool
HasNumber bool HasNumber bool
HasSymbol bool HasSymbol bool
IsActive bool
} }
func (wm *WriteModel) Reduce() error { func (wm *PasswordComplexityPolicyWriteModel) Reduce() error {
for _, event := range wm.Events { for _, event := range wm.Events {
switch e := event.(type) { switch e := event.(type) {
case *AddedEvent: case *policy.PasswordComplexityPolicyAddedEvent:
wm.MinLength = e.MinLength wm.MinLength = e.MinLength
wm.HasLowercase = e.HasLowercase wm.HasLowercase = e.HasLowercase
wm.HasUpperCase = e.HasUpperCase wm.HasUpperCase = e.HasUpperCase
wm.HasNumber = e.HasNumber wm.HasNumber = e.HasNumber
wm.HasSymbol = e.HasSymbol wm.HasSymbol = e.HasSymbol
case *ChangedEvent: wm.IsActive = true
case *policy.PasswordComplexityPolicyChangedEvent:
wm.MinLength = e.MinLength wm.MinLength = e.MinLength
wm.HasLowercase = e.HasLowercase wm.HasLowercase = e.HasLowercase
wm.HasUpperCase = e.HasUpperCase wm.HasUpperCase = e.HasUpperCase
wm.HasNumber = e.HasNumber wm.HasNumber = e.HasNumber
wm.HasSymbol = e.HasSymbol wm.HasSymbol = e.HasSymbol
case *policy.PasswordComplexityPolicyRemovedEvent:
wm.IsActive = false
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()

View File

@ -1,25 +1,30 @@
package password_lockout package command
import ( import (
"github.com/caos/zitadel/internal/eventstore/v2" "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/v2/repository/policy"
) )
type WriteModel struct { type PasswordLockoutPolicyWriteModel struct {
eventstore.WriteModel eventstore.WriteModel
MaxAttempts uint64 MaxAttempts uint64
ShowLockOutFailures bool ShowLockOutFailures bool
IsActive bool
} }
func (wm *WriteModel) Reduce() error { func (wm *PasswordLockoutPolicyWriteModel) Reduce() error {
for _, event := range wm.Events { for _, event := range wm.Events {
switch e := event.(type) { switch e := event.(type) {
case *AddedEvent: case *policy.PasswordLockoutPolicyAddedEvent:
wm.MaxAttempts = e.MaxAttempts wm.MaxAttempts = e.MaxAttempts
wm.ShowLockOutFailures = e.ShowLockOutFailures wm.ShowLockOutFailures = e.ShowLockOutFailures
case *ChangedEvent: wm.IsActive = true
case *policy.PasswordLockoutPolicyChangedEvent:
wm.MaxAttempts = e.MaxAttempts wm.MaxAttempts = e.MaxAttempts
wm.ShowLockOutFailures = e.ShowLockOutFailures wm.ShowLockOutFailures = e.ShowLockOutFailures
case *policy.PasswordLockoutPolicyRemovedEvent:
wm.IsActive = false
} }
} }
return wm.WriteModel.Reduce() return wm.WriteModel.Reduce()

View File

@ -0,0 +1,65 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
func (r *CommandSide) StartSetup(ctx context.Context, iamID string, step domain.Step) (*iam_model.IAM, error) {
iamWriteModel, err := r.iamByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return nil, err
}
if iamWriteModel.SetUpStarted >= step || iamWriteModel.SetUpStarted != iamWriteModel.SetUpDone {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "setup error")
}
aggregate := IAMAggregateFromWriteModel(&iamWriteModel.WriteModel).PushEvents(iam_repo.NewSetupStepStartedEvent(ctx, step))
err = r.eventstore.PushAggregate(ctx, iamWriteModel, aggregate)
if err != nil {
return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-Grgh1", "Setup start failed")
}
return writeModelToIAM(iamWriteModel), nil
}
//func (r *CommandSide) setupDone(ctx context.Context, iamAgg *iam_repo.Aggregate, event eventstore.EventPusher, aggregates ...eventstore.Aggregater) error {
// aggregate := iamAgg.PushEvents(event)
//
// aggregates = append(aggregates, aggregate)
// _, err := r.eventstore.PushAggregates(ctx, aggregates...)
// if err != nil {
// return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Dgd2", "Setup done failed")
// }
// return nil
//}
//
////TODO: should not use readmodel
//func (r *CommandSide) setup(ctx context.Context, iamID string, step iam_repo.Step, event eventstore.EventPusher) (*iam_model.IAM, error) {
// iam, err := r.iamByID(ctx, iamID)
// if err != nil && !caos_errs.IsNotFound(err) {
// return nil, err
// }
//
// if iam != nil && (iam.SetUpStarted >= iam_repo.Step(step) || iam.SetUpStarted != iam.SetUpDone) {
// return nil, caos_errs.ThrowPreconditionFailed(nil, "EVENT-9so34", "setup error")
// }
//
// aggregate := query.AggregateFromReadModel(iam).
// PushEvents(event)
//
// events, err := r.eventstore.PushAggregates(ctx, aggregate)
// if err != nil {
// return nil, err
// }
//
// if err = iam.AppendAndReduce(events...); err != nil {
// return nil, err
// }
// return nil, nil
// //TODO: return write model
// //return readModelToIAM(iam), nil
//}

View File

@ -0,0 +1,107 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
type Step1 struct {
GlobalOrg string
IAMProject string
DefaultLoginPolicy LoginPolicy //*iam_model.LoginPolicy
Orgs []Org
Owners []string
//setup *Setup
//createdUsers map[string]*usr_model.User
//createdOrgs map[string]*org_model.Org
//createdProjects map[string]*proj_model.Project
//pwComplexityPolicy *iam_model.PasswordComplexityPolicyView
}
type LoginPolicy struct {
AllowRegister bool
AllowUsernamePassword bool
AllowExternalIdp bool
}
type User struct {
FirstName string
LastName string
UserName string
Email string
Password string
}
type Org struct {
Name string
Domain string
OrgIamPolicy bool
Users []User
Owners []string
Projects []Project
}
type Project struct {
Name string
Users []User
Members []string
OIDCApps []OIDCApp
}
type OIDCApp struct {
Name string
RedirectUris []string
ResponseTypes []string
GrantTypes []string
ApplicationType string
AuthMethodType string
PostLogoutRedirectUris []string
DevMode bool
}
func (r *CommandSide) SetupStep1(ctx context.Context, iamID string, step1 Step1) error {
iam, err := r.iamByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return err
}
//create default login policy
iamAgg, err := r.addDefaultLoginPolicy(ctx,
NewIAMLoginPolicyWriteModel(iam.AggregateID),
&iam_model.LoginPolicy{
AllowUsernamePassword: step1.DefaultLoginPolicy.AllowUsernamePassword,
AllowRegister: step1.DefaultLoginPolicy.AllowRegister,
AllowExternalIdp: step1.DefaultLoginPolicy.AllowExternalIdp,
})
if err != nil {
return err
}
//create orgs
//create projects
//create applications
//set iam owners
//set global org
//set iam project id
/*aggregates:
iam:
default login policy
iam owner
org:
default
caos
zitadel
*/
iamAgg.PushEvents(iam_repo.NewSetupStepDoneEvent(ctx, domain.Step1))
_, err = r.eventstore.PushAggregates(ctx, iamAgg)
if err != nil {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-Gr2hh", "Setup Step1 failed")
}
return nil
}

View File

@ -0,0 +1,38 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
iam_model "github.com/caos/zitadel/internal/iam/model"
"github.com/caos/zitadel/internal/v2/domain"
iam_repo "github.com/caos/zitadel/internal/v2/repository/iam"
)
type Step2 struct {
DefaultPasswordComplexityPolicy iam_model.PasswordComplexityPolicy
}
func (r *CommandSide) SetupStep2(ctx context.Context, iamID string, step Step2) error {
iam, err := r.iamByID(ctx, iamID)
if err != nil && !caos_errs.IsNotFound(err) {
return err
}
iamAgg, err := r.addDefaultPasswordComplexityPolicy(ctx, NewIAMPasswordComplexityPolicyWriteModel(iam.AggregateID), &iam_model.PasswordComplexityPolicy{
MinLength: step.DefaultPasswordComplexityPolicy.MinLength,
HasLowercase: step.DefaultPasswordComplexityPolicy.HasLowercase,
HasUppercase: step.DefaultPasswordComplexityPolicy.HasUppercase,
HasNumber: step.DefaultPasswordComplexityPolicy.HasNumber,
HasSymbol: step.DefaultPasswordComplexityPolicy.HasSymbol,
})
if err != nil {
return err
}
iamAgg.PushEvents(iam_repo.NewSetupStepDoneEvent(ctx, domain.Step1))
_, err = r.eventstore.PushAggregates(ctx, iamAgg)
if err != nil {
return caos_errs.ThrowPreconditionFailed(nil, "EVENT-HR2na", "Setup Step2 failed")
}
return nil
}

123
internal/v2/command/user.go Normal file
View File

@ -0,0 +1,123 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/user"
)
func (r *CommandSide) AddUser(ctx context.Context, user *usr_model.User) (*usr_model.User, error) {
if !user.IsValid() {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2N9fs", "Errors.User.Invalid")
}
if user.Human != nil {
human, err := r.AddHuman(ctx, user.ResourceOwner, user.UserName, user.Human)
if err != nil {
return nil, err
}
return &usr_model.User{UserName: user.UserName, Human: human}, nil
} else if user.Machine != nil {
}
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-8K0df", "Errors.User.TypeUndefined")
}
func (r *CommandSide) DeactivateUser(ctx context.Context, userID string) (*usr_model.User, error) {
existingUser, err := r.userWriteModelByID(ctx, userID)
if err != nil {
return nil, err
}
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-3M9ds", "Errors.User.NotFound")
}
if existingUser.UserState == domain.UserStateInactive {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-5M0sf", "Errors.User.AlreadyInactive")
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserDeactivatedEvent(ctx))
err = r.eventstore.PushAggregate(ctx, existingUser, userAgg)
if err != nil {
return nil, err
}
return writeModelToUser(existingUser), nil
}
func (r *CommandSide) ReactivateUser(ctx context.Context, userID string) (*usr_model.User, error) {
existingUser, err := r.userWriteModelByID(ctx, userID)
if err != nil {
return nil, err
}
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-4M0sd", "Errors.User.NotFound")
}
if existingUser.UserState != domain.UserStateInactive {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-6M0sf", "Errors.User.NotInactive")
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserReactivatedEvent(ctx))
err = r.eventstore.PushAggregate(ctx, existingUser, userAgg)
if err != nil {
return nil, err
}
return writeModelToUser(existingUser), nil
}
func (r *CommandSide) LockUser(ctx context.Context, userID string) (*usr_model.User, error) {
existingUser, err := r.userWriteModelByID(ctx, userID)
if err != nil {
return nil, err
}
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-5M9fs", "Errors.User.NotFound")
}
if existingUser.UserState != domain.UserStateActive && existingUser.UserState != domain.UserStateInitial {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-2M9fs", "Errors.User.ShouldBeActiveOrInitial")
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserLockedEvent(ctx))
err = r.eventstore.PushAggregate(ctx, existingUser, userAgg)
if err != nil {
return nil, err
}
return writeModelToUser(existingUser), nil
}
func (r *CommandSide) UnlockUser(ctx context.Context, userID string) (*usr_model.User, error) {
existingUser, err := r.userWriteModelByID(ctx, userID)
if err != nil {
return nil, err
}
if existingUser.UserState != domain.UserStateUnspecified || existingUser.UserState != domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-M0dos", "Errors.User.NotFound")
}
if existingUser.UserState != domain.UserStateLocked {
return nil, caos_errs.ThrowPreconditionFailed(nil, "COMMAND-4M0ds", "Errors.User.NotLocked")
}
userAgg := UserAggregateFromWriteModel(&existingUser.WriteModel)
userAgg.PushEvents(user.NewUserUnlockedEvent(ctx))
err = r.eventstore.PushAggregate(ctx, existingUser, userAgg)
if err != nil {
return nil, err
}
return writeModelToUser(existingUser), nil
}
func (r *CommandSide) userWriteModelByID(ctx context.Context, userID string) (writeModel *UserWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewUserWriteModel(userID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -0,0 +1,62 @@
package command
import (
"github.com/caos/zitadel/internal/user/model"
)
func writeModelToUser(wm *UserWriteModel) *model.User {
return &model.User{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
UserName: wm.UserName,
State: model.UserState(wm.UserState),
}
}
func writeModelToHuman(wm *HumanWriteModel) *model.Human {
return &model.Human{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
Profile: &model.Profile{
FirstName: wm.FirstName,
LastName: wm.LastName,
NickName: wm.NickName,
DisplayName: wm.DisplayName,
PreferredLanguage: wm.PreferredLanguage,
Gender: model.Gender(wm.Gender),
},
Email: &model.Email{
EmailAddress: wm.Email,
IsEmailVerified: wm.IsEmailVerified,
},
}
}
func writeModelToProfile(wm *HumanProfileWriteModel) *model.Profile {
return &model.Profile{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
FirstName: wm.FirstName,
LastName: wm.LastName,
NickName: wm.NickName,
DisplayName: wm.DisplayName,
PreferredLanguage: wm.PreferredLanguage,
Gender: model.Gender(wm.Gender),
}
}
func writeModelToEmail(wm *HumanEmailWriteModel) *model.Email {
return &model.Email{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
EmailAddress: wm.Email,
IsEmailVerified: wm.IsEmailVerified,
}
}
func writeModelToAddress(wm *HumanAddressWriteModel) *model.Address {
return &model.Address{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
Country: wm.Country,
Locality: wm.Locality,
PostalCode: wm.PostalCode,
Region: wm.Region,
StreetAddress: wm.StreetAddress,
}
}

View File

@ -0,0 +1,71 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/domain"
"github.com/caos/zitadel/internal/v2/repository/user"
)
func (r *CommandSide) AddHuman(ctx context.Context, orgID, username string, human *usr_model.Human) (*usr_model.Human, error) {
if !human.IsValid() {
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-4M90d", "Errors.User.Invalid")
}
userID, err := r.idGenerator.Next()
if err != nil {
return nil, err
}
human.AggregateID = userID
orgIAMPolicy, err := r.GetOrgIAMPolicy(ctx, orgID)
if err != nil {
return nil, err
}
//pwPolicy, err := r.GetOrgPasswordComplexityPolicy(ctx, orgID)
//if err != nil {
// return nil, err
//}
addedHuman := NewHumanWriteModel(human.AggregateID)
//TODO: Check Unique Username
human.CheckOrgIAMPolicy(username, orgIAMPolicy)
human.SetNamesAsDisplayname()
//human.HashPasswordIfExisting(pwPolicy, r.userPasswordAlg, true)
userAgg := UserAggregateFromWriteModel(&addedHuman.WriteModel)
userAgg.PushEvents(
user.NewHumanAddedEvent(
ctx,
username,
human.FirstName,
human.LastName,
human.NickName,
human.DisplayName,
human.PreferredLanguage,
domain.Gender(human.Gender),
human.EmailAddress,
human.PhoneNumber,
human.Country,
human.Locality,
human.PostalCode,
human.Region,
human.StreetAddress,
),
)
//TODO: HashPassword If existing
//TODO: Generate Init Code if needed
//TODO: Generate Phone Code if needed
if human.Email != nil && human.EmailAddress != "" && human.IsEmailVerified {
userAgg.PushEvents(user.NewHumanEmailVerifiedEvent(ctx))
}
if human.Phone != nil && human.PhoneNumber != "" && human.IsPhoneVerified {
userAgg.PushEvents(user.NewHumanPhoneVerifiedEvent(ctx))
}
err = r.eventstore.PushAggregate(ctx, addedHuman, userAgg)
if err != nil {
return nil, err
}
return writeModelToHuman(addedHuman), nil
}

View File

@ -0,0 +1,44 @@
package command
import (
"context"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/telemetry/tracing"
usr_model "github.com/caos/zitadel/internal/user/model"
"github.com/caos/zitadel/internal/v2/domain"
)
func (r *CommandSide) ChangeHumanAddress(ctx context.Context, address *usr_model.Address) (*usr_model.Address, error) {
existingAddress, err := r.addressWriteModel(ctx, address.AggregateID)
if err != nil {
return nil, err
}
if existingAddress.UserState == domain.UserStateUnspecified || existingAddress.UserState == domain.UserStateDeleted {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-0pLdo", "Errors.User.Address.NotFound")
}
changedEvent, hasChanged := existingAddress.NewChangedEvent(ctx, address.Country, address.Locality, address.PostalCode, address.Region, address.StreetAddress)
if !hasChanged {
return nil, caos_errs.ThrowAlreadyExists(nil, "COMMAND-3M0cs", "Errors.User.Address.NotChanged")
}
userAgg := UserAggregateFromWriteModel(&existingAddress.WriteModel)
userAgg.PushEvents(changedEvent)
err = r.eventstore.PushAggregate(ctx, existingAddress, userAgg)
if err != nil {
return nil, err
}
return writeModelToAddress(existingAddress), nil
}
func (r *CommandSide) addressWriteModel(ctx context.Context, userID string) (writeModel *HumanAddressWriteModel, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewHumanAddressWriteModel(userID)
err = r.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

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