diff --git a/internal/admin/repository/eventsourcing/eventstore/iam.go b/internal/admin/repository/eventsourcing/eventstore/iam.go index 1b2683dbec..d48e53d9f5 100644 --- a/internal/admin/repository/eventsourcing/eventstore/iam.go +++ b/internal/admin/repository/eventsourcing/eventstore/iam.go @@ -98,7 +98,8 @@ func (repo *IAMRepository) GetIAMMemberRoles() []string { func (repo *IAMRepository) IDPConfigByID(ctx context.Context, idpConfigID string) (*iam_model.IDPConfigView, error) { if repo.IAMV2 != nil { - return repo.IAMV2.IDPConfigByID(ctx, idpConfigID) + + return repo.IAMV2.IDPConfigByID(ctx, repo.SystemDefaults.IamID, idpConfigID) } idp, err := repo.View.IDPConfigByID(idpConfigID) @@ -118,6 +119,9 @@ func (repo *IAMRepository) AddOIDCIDPConfig(ctx context.Context, idp *iam_model. func (repo *IAMRepository) ChangeIDPConfig(ctx context.Context, idp *iam_model.IDPConfig) (*iam_model.IDPConfig, error) { idp.AggregateID = repo.SystemDefaults.IamID + if repo.IAMV2 != nil { + return repo.IAMV2.ChangeIDPConfig(ctx, idp) + } return repo.IAMEventstore.ChangeIDPConfig(ctx, idp) } @@ -172,6 +176,9 @@ func (repo *IAMRepository) RemoveIDPConfig(ctx context.Context, idpConfigID stri func (repo *IAMRepository) ChangeOidcIDPConfig(ctx context.Context, oidcConfig *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) { oidcConfig.AggregateID = repo.SystemDefaults.IamID + if repo.IAMV2 != nil { + return repo.IAMV2.ChangeIDPOIDCConfig(ctx, oidcConfig) + } return repo.IAMEventstore.ChangeIDPOIDCConfig(ctx, oidcConfig) } diff --git a/internal/eventstore/spooler/spooler.go b/internal/eventstore/spooler/spooler.go index d670d7cfdd..d95f45ad4a 100644 --- a/internal/eventstore/spooler/spooler.go +++ b/internal/eventstore/spooler/spooler.go @@ -50,10 +50,12 @@ func (s *Spooler) Start() { } }(i) } - for _, handler := range s.handlers { - handler := &spooledHandler{Handler: handler, locker: s.locker, queuedAt: time.Now(), eventstore: s.eventstore} - s.queue <- handler - } + go func() { + for _, handler := range s.handlers { + handler := &spooledHandler{Handler: handler, locker: s.locker, queuedAt: time.Now(), eventstore: s.eventstore} + s.queue <- handler + } + }() } func requeueTask(task *spooledHandler, queue chan<- *spooledHandler) { diff --git a/internal/eventstore/v2/repository/sql/crdb.go b/internal/eventstore/v2/repository/sql/crdb.go index 869accd282..f8adcd27b9 100644 --- a/internal/eventstore/v2/repository/sql/crdb.go +++ b/internal/eventstore/v2/repository/sql/crdb.go @@ -170,7 +170,8 @@ func (db *CRDB) Push(ctx context.Context, events ...*repository.Event) error { "aggregate", event.AggregateType, "aggregateId", event.AggregateID, "aggregateType", event.AggregateType, - "eventType", event.Type).WithError(err).Info("query failed") + "eventType", event.Type).WithError(err).Info("query failed", + "seq", event.PreviousSequence) return caos_errs.ThrowInternal(err, "SQL-SBP37", "unable to create event") } } diff --git a/internal/v2/business/iam/converter.go b/internal/v2/business/iam/converter.go index bc8b047d64..b71e5311f5 100644 --- a/internal/v2/business/iam/converter.go +++ b/internal/v2/business/iam/converter.go @@ -6,7 +6,6 @@ import ( "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/idp" "github.com/caos/zitadel/internal/v2/repository/idp/oidc" "github.com/caos/zitadel/internal/v2/repository/member" ) @@ -143,7 +142,7 @@ func readModelToIDPConfigView(rm *iam.IDPConfigReadModel) *model.IDPConfigView { CreationDate: rm.CreationDate, IDPConfigID: rm.ConfigID, IDPProviderType: model.IDPProviderType(rm.ProviderType), - IsOIDC: rm.Type == idp.ConfigTypeOIDC, + IsOIDC: rm.OIDCConfig != nil, Name: rm.Name, OIDCClientID: rm.OIDCConfig.ClientID, OIDCClientSecret: rm.OIDCConfig.ClientSecret, @@ -161,7 +160,6 @@ func readModelToIDPConfig(rm *iam.IDPConfigReadModel) *model.IDPConfig { return &model.IDPConfig{ ObjectRoot: readModelToObjectRoot(rm.ReadModel), OIDCConfig: readModelToIDPOIDCConfig(rm.OIDCConfig), - Type: model.IdpConfigType(rm.Type), IDPConfigID: rm.ConfigID, Name: rm.Name, State: model.IDPConfigState(rm.State), @@ -182,3 +180,26 @@ func readModelToIDPOIDCConfig(rm *oidc.ConfigReadModel) *model.OIDCIDPConfig { 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), + } +} diff --git a/internal/v2/business/iam/idp_config.go b/internal/v2/business/iam/idp_config.go new file mode 100644 index 0000000000..eb6c7fdef8 --- /dev/null +++ b/internal/v2/business/iam/idp_config.go @@ -0,0 +1,94 @@ +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 + } + wm := iam.NewIDPConfigWriteModel(config.AggregateID, idpConfigID) + err = r.eventstore.FilterToQueryReducer(ctx, wm) + if err != nil { + return nil, err + } + + clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.secretCrypto) + if err != nil { + return nil, err + } + + aggregate := iam.AggregateFromWriteModel(&wm.WriteModel). + 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...) + + events, err := r.eventstore.PushAggregates(ctx, aggregate) + if err != nil { + return nil, err + } + + if err = wm.AppendAndReduce(events...); err != nil { + return nil, err + } + + return writeModelToIDPConfig(wm), nil +} + +func (r *Repository) ChangeIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) { + writeModel := iam.NewIDPConfigWriteModel(config.AggregateID, config.IDPConfigID) + err := r.eventstore.FilterToQueryReducer(ctx, writeModel) + if err != nil { + return nil, err + } + + aggregate := iam.AggregateFromWriteModel(&writeModel.WriteModel). + PushIDPConfigChanged( + ctx, + writeModel, + config.IDPConfigID, + config.Name, + idp.ConfigType(config.Type), + idp.StylingType(config.StylingType)) + + events, err := r.eventstore.PushAggregates(ctx, aggregate) + if err != nil { + return nil, err + } + + if err = writeModel.AppendAndReduce(events...); err != nil { + return nil, err + } + + return writeModelToIDPConfig(writeModel), nil +} diff --git a/internal/v2/business/iam/idp_oidc_config.go b/internal/v2/business/iam/idp_oidc_config.go index c999a80532..0a2f983eb8 100644 --- a/internal/v2/business/iam/idp_oidc_config.go +++ b/internal/v2/business/iam/idp_oidc_config.go @@ -4,78 +4,48 @@ import ( "context" "github.com/caos/zitadel/internal/crypto" - "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/eventstore/v2" 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, idpConfigID string) (*iam_model.IDPConfigView, error) { - query := eventstore.NewSearchQueryFactory(eventstore.ColumnsEvent, iam.AggregateType). - EventData(map[string]interface{}{ - "idpConfigId": idpConfigID, - }) +func (r *Repository) ChangeIDPOIDCConfig(ctx context.Context, config *iam_model.OIDCIDPConfig) (*iam_model.OIDCIDPConfig, error) { + writeModel := iam.NewIDPOIDCConfigWriteModel(config.AggregateID, config.IDPConfigID) - idpConfig := new(iam.IDPConfigReadModel) - - events, err := r.eventstore.FilterEvents(ctx, query) + err := r.eventstore.FilterToQueryReducer(ctx, writeModel) if err != nil { return nil, err } - idpConfig.AppendEvents(events...) - if err = idpConfig.Reduce(); err != nil { - return nil, err - } + var clientSecret *crypto.CryptoValue - return readModelToIDPConfigView(idpConfig), nil -} - -func (r *Repository) AddIDPConfig(ctx context.Context, config *iam_model.IDPConfig) (*iam_model.IDPConfig, error) { - readModel, err := r.iamByID(ctx, config.AggregateID) - if err != nil { - return nil, err - } - - idpConfigID, err := r.idGenerator.Next() - if err != nil { - return nil, err - } - - aggregate := iam.AggregateFromReadModel(readModel). - PushIDPConfigAdded(ctx, idpConfigID, config.Name, idp.ConfigType(config.Type), idp.StylingType(config.StylingType)) - - if config.OIDCConfig != nil { - clientSecret, err := crypto.Crypt([]byte(config.OIDCConfig.ClientSecretString), r.secretCrypto) + if config.ClientSecretString != "" { + clientSecret, err = crypto.Crypt([]byte(config.ClientSecretString), r.secretCrypto) if err != nil { return nil, err } - aggregate = aggregate.PushIDPOIDCConfigAdded( - ctx, - config.OIDCConfig.ClientID, - idpConfigID, - config.OIDCConfig.Issuer, - clientSecret, - oidc.MappingField(config.OIDCConfig.IDPDisplayNameMapping), - oidc.MappingField(config.OIDCConfig.UsernameMapping), - config.OIDCConfig.Scopes...) } + aggregate := iam.AggregateFromWriteModel(&writeModel.ConfigWriteModel.WriteModel). + PushIDPOIDCConfigChanged( + ctx, + writeModel, + config.ClientID, + config.Issuer, + clientSecret, + oidc.MappingField(config.IDPDisplayNameMapping), + oidc.MappingField(config.UsernameMapping), + config.Scopes...) + events, err := r.eventstore.PushAggregates(ctx, aggregate) if err != nil { return nil, err } - if err = readModel.AppendAndReduce(events...); err != nil { + writeModel.AppendEvents(events...) + if err = writeModel.Reduce(); err != nil { return nil, err } - idpConfig := readModel.IDPByID(idpConfigID) - if idpConfig == nil { - return nil, errors.ThrowInternal(nil, "IAM-stZYB", "Errors.Internal") - } - - return readModelToIDPConfig(idpConfig), nil + return writeModelToIDPOIDCConfig(&writeModel.ConfigWriteModel), nil } diff --git a/internal/v2/business/iam/member.go b/internal/v2/business/iam/member.go index 951e512ad5..e75a1262c5 100644 --- a/internal/v2/business/iam/member.go +++ b/internal/v2/business/iam/member.go @@ -102,13 +102,16 @@ func (r *Repository) MemberByID(ctx context.Context, iamID, userID string) (memb ctx, span := tracing.NewSpan(ctx) defer func() { span.EndWithError(err) }() + member = new(iam_repo.MemberReadModel) + + //query view + query := eventstore.NewSearchQueryFactory(eventstore.ColumnsEvent, iam_repo.AggregateType). AggregateIDs(iamID). EventData(map[string]interface{}{ "userId": userID, - }) + }).SequenceGreater(member.ProcessedSequence) - member = new(iam_repo.MemberReadModel) err = r.eventstore.FilterToReducer(ctx, query, member) if err != nil { return nil, err diff --git a/internal/v2/repository/iam/aggregate.go b/internal/v2/repository/iam/aggregate.go index b94c2f453e..5430583028 100644 --- a/internal/v2/repository/iam/aggregate.go +++ b/internal/v2/repository/iam/aggregate.go @@ -153,14 +153,13 @@ func (a *Aggregate) PushIDPOIDCConfigChanged( ctx context.Context, current *IDPOIDCConfigWriteModel, clientID, - idpConfigID, issuer string, clientSecret *crypto.CryptoValue, idpDisplayNameMapping, userNameMapping oidc.MappingField, scopes ...string, ) *Aggregate { - event, err := NewIDPOIDCConfigChangedEvent(ctx, current, clientID, idpConfigID, issuer, clientSecret, idpDisplayNameMapping, userNameMapping, scopes...) + event, err := NewIDPOIDCConfigChangedEvent(ctx, current, clientID, issuer, clientSecret, idpDisplayNameMapping, userNameMapping, scopes...) if err != nil { return a } diff --git a/internal/v2/repository/iam/idp_config.go b/internal/v2/repository/iam/idp_config.go index dc4a834e3d..eba41591e7 100644 --- a/internal/v2/repository/iam/idp_config.go +++ b/internal/v2/repository/iam/idp_config.go @@ -18,6 +18,16 @@ const ( type IDPConfigReadModel struct { idp.ConfigReadModel + + iamID string + configID string +} + +func NewIDPConfigReadModel(iamID, configID string) *IDPConfigReadModel { + return &IDPConfigReadModel{ + iamID: iamID, + configID: configID, + } } func (rm *IDPConfigReadModel) AppendEvents(events ...eventstore.EventReader) { @@ -41,34 +51,89 @@ func (rm *IDPConfigReadModel) AppendEvents(events ...eventstore.EventReader) { } } -type IDPConfigWriteModel struct { - idp.ConfigWriteModel +func (rm *IDPConfigReadModel) Query() *eventstore.SearchQueryFactory { + return eventstore.NewSearchQueryFactory(eventstore.ColumnsEvent, AggregateType). + AggregateIDs(rm.iamID). + EventData(map[string]interface{}{ + "idpConfigId": rm.configID, + }) } -func (rm *IDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) { +type IDPConfigWriteModel struct { + eventstore.WriteModel + idp.ConfigWriteModel + + iamID string + configID string +} + +func NewIDPConfigWriteModel(iamID, configID string) *IDPConfigWriteModel { + return &IDPConfigWriteModel{ + iamID: iamID, + configID: configID, + } +} + +func (wm *IDPConfigWriteModel) Query() *eventstore.SearchQueryFactory { + return eventstore.NewSearchQueryFactory(eventstore.ColumnsEvent, AggregateType). + AggregateIDs(wm.iamID) +} + +func (wm *IDPConfigWriteModel) AppendEvents(events ...eventstore.EventReader) { + wm.WriteModel.AppendEvents(events...) for _, event := range events { switch e := event.(type) { case *IDPConfigAddedEvent: - rm.ConfigWriteModel.AppendEvents(&e.ConfigAddedEvent) + if wm.configID != e.ConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigAddedEvent) case *IDPConfigChangedEvent: - rm.ConfigWriteModel.AppendEvents(&e.ConfigChangedEvent) + if wm.configID != e.ConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigChangedEvent) case *IDPConfigDeactivatedEvent: - rm.ConfigWriteModel.AppendEvents(&e.ConfigDeactivatedEvent) + if wm.configID != e.ConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigDeactivatedEvent) case *IDPConfigReactivatedEvent: - rm.ConfigWriteModel.AppendEvents(&e.ConfigReactivatedEvent) + if wm.configID != e.ConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigReactivatedEvent) case *IDPConfigRemovedEvent: - rm.ConfigWriteModel.AppendEvents(&e.ConfigRemovedEvent) - case *idp.ConfigAddedEvent, - *idp.ConfigChangedEvent, - *idp.ConfigDeactivatedEvent, - *idp.ConfigReactivatedEvent, - *idp.ConfigRemovedEvent: - - rm.ConfigWriteModel.AppendEvents(e) + if wm.configID != e.ConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigRemovedEvent) + case *IDPOIDCConfigAddedEvent: + if wm.configID != e.IDPConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigAddedEvent) + case *IDPOIDCConfigChangedEvent: + if wm.configID != e.IDPConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigChangedEvent) } } } +func (wm *IDPConfigWriteModel) Reduce() error { + if err := wm.ConfigWriteModel.Reduce(); err != nil { + return err + } + return wm.WriteModel.Reduce() +} + +func (wm *IDPConfigWriteModel) AppendAndReduce(events ...eventstore.EventReader) error { + wm.AppendEvents(events...) + return wm.Reduce() +} + type IDPConfigAddedEvent struct { idp.ConfigAddedEvent } diff --git a/internal/v2/repository/iam/idp_oidc_config.go b/internal/v2/repository/iam/idp_oidc_config.go index 6356b94777..659af88c92 100644 --- a/internal/v2/repository/iam/idp_oidc_config.go +++ b/internal/v2/repository/iam/idp_oidc_config.go @@ -16,19 +16,38 @@ const ( type IDPOIDCConfigWriteModel struct { oidc.ConfigWriteModel + + iamID string + idpConfigID string } -func (rm *IDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) { +func NewIDPOIDCConfigWriteModel(iamID, idpConfigID string) *IDPOIDCConfigWriteModel { + return &IDPOIDCConfigWriteModel{ + iamID: iamID, + idpConfigID: idpConfigID, + } +} + +func (wm *IDPOIDCConfigWriteModel) Query() *eventstore.SearchQueryFactory { + return eventstore.NewSearchQueryFactory(eventstore.ColumnsEvent, AggregateType). + AggregateIDs(wm.iamID) +} + +func (wm *IDPOIDCConfigWriteModel) AppendEvents(events ...eventstore.EventReader) { for _, event := range events { switch e := event.(type) { case *IDPOIDCConfigAddedEvent: - rm.ConfigWriteModel.AppendEvents(&e.ConfigAddedEvent) + if wm.idpConfigID != e.IDPConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigAddedEvent) case *IDPOIDCConfigChangedEvent: - rm.ConfigWriteModel.AppendEvents(&e.ConfigChangedEvent) - case *oidc.ConfigAddedEvent, - *oidc.ConfigChangedEvent: - - rm.ConfigWriteModel.AppendEvents(e) + if wm.idpConfigID != e.IDPConfigID { + continue + } + wm.ConfigWriteModel.AppendEvents(&e.ConfigChangedEvent) + default: + wm.ConfigWriteModel.AppendEvents(e) } } } @@ -82,7 +101,6 @@ func NewIDPOIDCConfigChangedEvent( ctx context.Context, current *IDPOIDCConfigWriteModel, clientID, - idpConfigID, issuer string, clientSecret *crypto.CryptoValue, idpDisplayNameMapping, @@ -93,7 +111,7 @@ func NewIDPOIDCConfigChangedEvent( event, err := oidc.NewConfigChangedEvent( eventstore.NewBaseEventForPush( ctx, - IDPOIDCConfigAddedEventType, + IDPOIDCConfigChangedEventType, ), ¤t.ConfigWriteModel, clientID, diff --git a/internal/v2/repository/idp/config_read_model.go b/internal/v2/repository/idp/config_read_model.go index 3e071ec02c..b7ec3a60d9 100644 --- a/internal/v2/repository/idp/config_read_model.go +++ b/internal/v2/repository/idp/config_read_model.go @@ -8,8 +8,6 @@ import ( type ConfigReadModel struct { eventstore.ReadModel - Type ConfigType - State ConfigState ConfigID string Name string @@ -26,13 +24,24 @@ func NewConfigReadModel(configID string) *ConfigReadModel { } func (rm *ConfigReadModel) AppendEvents(events ...eventstore.EventReader) { - rm.ReadModel.AppendEvents(events...) for _, event := range events { - switch event.(type) { + switch e := event.(type) { + case *ConfigAddedEvent: + rm.ReadModel.AppendEvents(e) + case *ConfigChangedEvent: + rm.ReadModel.AppendEvents(e) + case *ConfigDeactivatedEvent: + rm.ReadModel.AppendEvents(e) + case *ConfigReactivatedEvent: + rm.ReadModel.AppendEvents(e) + case *ConfigRemovedEvent: + rm.ReadModel.AppendEvents(e) case *oidc.ConfigAddedEvent: rm.OIDCConfig = &oidc.ConfigReadModel{} + rm.ReadModel.AppendEvents(e) rm.OIDCConfig.AppendEvents(event) case *oidc.ConfigChangedEvent: + rm.ReadModel.AppendEvents(e) rm.OIDCConfig.AppendEvents(event) } } @@ -42,30 +51,42 @@ func (rm *ConfigReadModel) Reduce() error { for _, event := range rm.Events { switch e := event.(type) { case *ConfigAddedEvent: - rm.ConfigID = e.ConfigID - rm.Name = e.Name - rm.StylingType = e.StylingType - rm.State = ConfigStateActive + rm.reduceConfigAddedEvent(e) case *ConfigChangedEvent: - if e.Name != "" { - rm.Name = e.Name - } - if e.StylingType.Valid() { - rm.StylingType = e.StylingType - } + rm.reduceConfigChangedEvent(e) case *ConfigDeactivatedEvent: - rm.State = ConfigStateInactive + rm.reduceConfigStateChanged(e.ConfigID, ConfigStateInactive) case *ConfigReactivatedEvent: - rm.State = ConfigStateActive + rm.reduceConfigStateChanged(e.ConfigID, ConfigStateActive) case *ConfigRemovedEvent: - rm.State = ConfigStateRemoved - case *oidc.ConfigAddedEvent: - rm.Type = ConfigTypeOIDC + rm.reduceConfigStateChanged(e.ConfigID, ConfigStateRemoved) } } - if err := rm.OIDCConfig.Reduce(); err != nil { - return err + if rm.OIDCConfig != nil { + if err := rm.OIDCConfig.Reduce(); err != nil { + return err + } } return rm.ReadModel.Reduce() } + +func (rm *ConfigReadModel) reduceConfigAddedEvent(e *ConfigAddedEvent) { + rm.ConfigID = e.ConfigID + rm.Name = e.Name + rm.StylingType = e.StylingType + rm.State = ConfigStateActive +} + +func (rm *ConfigReadModel) reduceConfigChangedEvent(e *ConfigChangedEvent) { + if e.Name != "" { + rm.Name = e.Name + } + if e.StylingType.Valid() { + rm.StylingType = e.StylingType + } +} + +func (rm *ConfigReadModel) reduceConfigStateChanged(configID string, state ConfigState) { + rm.State = state +} diff --git a/internal/v2/repository/idp/config_write_model.go b/internal/v2/repository/idp/config_write_model.go index 1f297a02a8..d04f68550b 100644 --- a/internal/v2/repository/idp/config_write_model.go +++ b/internal/v2/repository/idp/config_write_model.go @@ -8,10 +8,13 @@ import ( type ConfigWriteModel struct { eventstore.WriteModel + State ConfigState + ConfigID string Name string StylingType StylingType - OIDCConfig *oidc.ConfigWriteModel + + OIDCConfig *oidc.ConfigWriteModel } func (rm *ConfigWriteModel) AppendEvents(events ...eventstore.EventReader) { @@ -19,7 +22,7 @@ func (rm *ConfigWriteModel) AppendEvents(events ...eventstore.EventReader) { for _, event := range events { switch event.(type) { case *oidc.ConfigAddedEvent: - rm.OIDCConfig = &oidc.ConfigWriteModel{} + rm.OIDCConfig = new(oidc.ConfigWriteModel) rm.OIDCConfig.AppendEvents(event) case *oidc.ConfigChangedEvent: rm.OIDCConfig.AppendEvents(event) @@ -31,20 +34,41 @@ func (rm *ConfigWriteModel) Reduce() error { for _, event := range rm.Events { switch e := event.(type) { case *ConfigAddedEvent: - rm.ConfigID = e.ConfigID - rm.Name = e.Name - rm.StylingType = e.StylingType + rm.reduceConfigAddedEvent(e) case *ConfigChangedEvent: - if e.Name != "" { - rm.Name = e.Name - } - if e.StylingType.Valid() { - rm.StylingType = e.StylingType - } + rm.reduceConfigChangedEvent(e) + case *ConfigDeactivatedEvent: + rm.reduceConfigStateChanged(e.ConfigID, ConfigStateInactive) + case *ConfigReactivatedEvent: + rm.reduceConfigStateChanged(e.ConfigID, ConfigStateActive) + case *ConfigRemovedEvent: + rm.reduceConfigStateChanged(e.ConfigID, ConfigStateRemoved) } } - if err := rm.OIDCConfig.Reduce(); err != nil { - return err + if rm.OIDCConfig != nil { + if err := rm.OIDCConfig.Reduce(); err != nil { + return err + } } return rm.WriteModel.Reduce() } + +func (rm *ConfigWriteModel) reduceConfigAddedEvent(e *ConfigAddedEvent) { + rm.ConfigID = e.ConfigID + rm.Name = e.Name + rm.StylingType = e.StylingType + rm.State = ConfigStateActive +} + +func (rm *ConfigWriteModel) reduceConfigChangedEvent(e *ConfigChangedEvent) { + if e.Name != "" { + rm.Name = e.Name + } + if e.StylingType.Valid() { + rm.StylingType = e.StylingType + } +} + +func (rm *ConfigWriteModel) reduceConfigStateChanged(configID string, state ConfigState) { + rm.State = state +} diff --git a/internal/v2/repository/idp/event_config_added.go b/internal/v2/repository/idp/event_config_added.go index a032109566..5b94cfc41c 100644 --- a/internal/v2/repository/idp/event_config_added.go +++ b/internal/v2/repository/idp/event_config_added.go @@ -12,7 +12,7 @@ type ConfigAddedEvent struct { eventstore.BaseEvent `json:"-"` ConfigID string `json:"idpConfigId"` - Name string `json:"name"` + Name string `json:"name,omitempty"` Typ ConfigType `json:"idpType,omitempty"` StylingType StylingType `json:"stylingType,omitempty"` } diff --git a/internal/v2/repository/idp/oidc/config_read_model.go b/internal/v2/repository/idp/oidc/config_read_model.go index 338a6a35c7..024cef0aa7 100644 --- a/internal/v2/repository/idp/oidc/config_read_model.go +++ b/internal/v2/repository/idp/oidc/config_read_model.go @@ -21,31 +21,39 @@ func (rm *ConfigReadModel) Reduce() error { for _, event := range rm.Events { switch e := event.(type) { case *ConfigAddedEvent: - rm.IDPConfigID = e.IDPConfigID - rm.ClientID = e.ClientID - rm.ClientSecret = e.ClientSecret - rm.Issuer = e.Issuer - rm.Scopes = e.Scopes - rm.IDPDisplayNameMapping = e.IDPDisplayNameMapping - rm.UserNameMapping = e.UserNameMapping + rm.reduceConfigAddedEvent(e) case *ConfigChangedEvent: - if e.ClientID != "" { - rm.ClientID = e.ClientID - } - if e.Issuer != "" { - rm.Issuer = e.Issuer - } - if len(e.Scopes) > 0 { - rm.Scopes = e.Scopes - } - if e.IDPDisplayNameMapping.Valid() { - rm.IDPDisplayNameMapping = e.IDPDisplayNameMapping - } - if e.UserNameMapping.Valid() { - rm.UserNameMapping = e.UserNameMapping - } + rm.reduceConfigChangedEvent(e) } } return rm.ReadModel.Reduce() } + +func (rm *ConfigReadModel) reduceConfigAddedEvent(e *ConfigAddedEvent) { + rm.IDPConfigID = e.IDPConfigID + rm.ClientID = e.ClientID + rm.ClientSecret = e.ClientSecret + rm.Issuer = e.Issuer + rm.Scopes = e.Scopes + rm.IDPDisplayNameMapping = e.IDPDisplayNameMapping + rm.UserNameMapping = e.UserNameMapping +} + +func (rm *ConfigReadModel) reduceConfigChangedEvent(e *ConfigChangedEvent) { + if e.ClientID != "" { + rm.ClientID = e.ClientID + } + if e.Issuer != "" { + rm.Issuer = e.Issuer + } + if len(e.Scopes) > 0 { + rm.Scopes = e.Scopes + } + if e.IDPDisplayNameMapping.Valid() { + rm.IDPDisplayNameMapping = e.IDPDisplayNameMapping + } + if e.UserNameMapping.Valid() { + rm.UserNameMapping = e.UserNameMapping + } +} diff --git a/internal/v2/repository/idp/oidc/config_write_model.go b/internal/v2/repository/idp/oidc/config_write_model.go index 8b12e2998a..147772aadf 100644 --- a/internal/v2/repository/idp/oidc/config_write_model.go +++ b/internal/v2/repository/idp/oidc/config_write_model.go @@ -22,31 +22,39 @@ func (wm *ConfigWriteModel) Reduce() error { for _, event := range wm.Events { switch e := event.(type) { case *ConfigAddedEvent: - wm.IDPConfigID = e.IDPConfigID - wm.ClientID = e.ClientID - wm.ClientSecret = e.ClientSecret - wm.Issuer = e.Issuer - wm.Scopes = e.Scopes - wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping - wm.UserNameMapping = e.UserNameMapping + wm.reduceConfigAddedEvent(e) case *ConfigChangedEvent: - if e.ClientID != "" { - wm.ClientID = e.ClientID - } - if e.Issuer != "" { - wm.Issuer = e.Issuer - } - if len(e.Scopes) > 0 { - wm.Scopes = e.Scopes - } - if e.IDPDisplayNameMapping.Valid() { - wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping - } - if e.UserNameMapping.Valid() { - wm.UserNameMapping = e.UserNameMapping - } + wm.reduceConfigChangedEvent(e) } } return wm.WriteModel.Reduce() } + +func (wm *ConfigWriteModel) reduceConfigAddedEvent(e *ConfigAddedEvent) { + wm.IDPConfigID = e.IDPConfigID + wm.ClientID = e.ClientID + wm.ClientSecret = e.ClientSecret + wm.Issuer = e.Issuer + wm.Scopes = e.Scopes + wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping + wm.UserNameMapping = e.UserNameMapping +} + +func (wm *ConfigWriteModel) reduceConfigChangedEvent(e *ConfigChangedEvent) { + if e.ClientID != "" { + wm.ClientID = e.ClientID + } + if e.Issuer != "" { + wm.Issuer = e.Issuer + } + if len(e.Scopes) > 0 { + wm.Scopes = e.Scopes + } + if e.IDPDisplayNameMapping.Valid() { + wm.IDPDisplayNameMapping = e.IDPDisplayNameMapping + } + if e.UserNameMapping.Valid() { + wm.UserNameMapping = e.UserNameMapping + } +} diff --git a/internal/v2/repository/idp/oidc/event_added.go b/internal/v2/repository/idp/oidc/event_added.go index fcd0d80736..542c1a0645 100644 --- a/internal/v2/repository/idp/oidc/event_added.go +++ b/internal/v2/repository/idp/oidc/event_added.go @@ -13,13 +13,13 @@ type ConfigAddedEvent struct { eventstore.BaseEvent IDPConfigID string `json:"idpConfigId"` - ClientID string `json:"clientId"` - ClientSecret *crypto.CryptoValue `json:"clientSecret"` - Issuer string `json:"issuer"` - Scopes []string `json:"scpoes"` + ClientID string `json:"clientId,omitempty"` + ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"` + Issuer string `json:"issuer,omitempty"` + Scopes []string `json:"scpoes,omitempty"` - IDPDisplayNameMapping MappingField `json:"idpDisplayNameMapping"` - UserNameMapping MappingField `json:"usernameMapping"` + IDPDisplayNameMapping MappingField `json:"idpDisplayNameMapping,omitempty"` + UserNameMapping MappingField `json:"usernameMapping,omitempty"` } func (e *ConfigAddedEvent) CheckPrevious() bool { diff --git a/internal/v2/repository/idp/oidc/event_changed.go b/internal/v2/repository/idp/oidc/event_changed.go index ddaa7866b5..195ff301f7 100644 --- a/internal/v2/repository/idp/oidc/event_changed.go +++ b/internal/v2/repository/idp/oidc/event_changed.go @@ -16,13 +16,13 @@ type ConfigChangedEvent struct { IDPConfigID string `json:"idpConfigId"` - ClientID string `json:"clientId"` - ClientSecret *crypto.CryptoValue `json:"clientSecret"` - Issuer string `json:"issuer"` - Scopes []string `json:"scpoes"` + ClientID string `json:"clientId,omitempty"` + ClientSecret *crypto.CryptoValue `json:"clientSecret,omitempty"` + Issuer string `json:"issuer,omitempty"` + Scopes []string `json:"scpoes,omitempty"` - IDPDisplayNameMapping MappingField `json:"idpDisplayNameMapping"` - UserNameMapping MappingField `json:"usernameMapping"` + IDPDisplayNameMapping MappingField `json:"idpDisplayNameMapping,omitempty"` + UserNameMapping MappingField `json:"usernameMapping,omitempty"` } func (e *ConfigChangedEvent) CheckPrevious() bool { @@ -60,7 +60,7 @@ func NewConfigChangedEvent( hasChanged = true } - if clientSecret != nil && clientSecret != current.ClientSecret { + if clientSecret != nil { event.ClientSecret = clientSecret hasChanged = true } diff --git a/internal/v2/repository/policy/label.go b/internal/v2/repository/policy/label.go index 42b3ada6c0..c42fb33c41 100644 --- a/internal/v2/repository/policy/label.go +++ b/internal/v2/repository/policy/label.go @@ -46,8 +46,8 @@ func (rm *LabelPolicyReadModel) Reduce() error { type LabelPolicyAddedEvent struct { eventstore.BaseEvent `json:"-"` - PrimaryColor string `json:"primaryColor"` - SecondaryColor string `json:"secondaryColor"` + PrimaryColor string `json:"primaryColor,omitempty"` + SecondaryColor string `json:"secondaryColor,omitempty"` } func (e *LabelPolicyAddedEvent) CheckPrevious() bool { diff --git a/internal/v2/repository/policy/password_complexity.go b/internal/v2/repository/policy/password_complexity.go index d00a1b32f0..45a8548685 100644 --- a/internal/v2/repository/policy/password_complexity.go +++ b/internal/v2/repository/policy/password_complexity.go @@ -58,7 +58,7 @@ func (rm *PasswordComplexityPolicyReadModel) Reduce() error { type PasswordComplexityPolicyAddedEvent struct { eventstore.BaseEvent `json:"-"` - MinLength uint8 `json:"minLength"` + MinLength uint8 `json:"minLength,omitempty"` HasLowercase bool `json:"hasLowercase"` HasUpperCase bool `json:"hasUppercase"` HasNumber bool `json:"hasNumber"` diff --git a/internal/v2/repository/policy/password_lockout.go b/internal/v2/repository/policy/password_lockout.go index 6e5bc9e2a0..735012081f 100644 --- a/internal/v2/repository/policy/password_lockout.go +++ b/internal/v2/repository/policy/password_lockout.go @@ -46,7 +46,7 @@ func (rm *PasswordLockoutPolicyReadModel) Reduce() error { type PasswordLockoutPolicyAddedEvent struct { eventstore.BaseEvent `json:"-"` - MaxAttempts uint8 `json:"maxAttempts"` + MaxAttempts uint8 `json:"maxAttempts,omitempty"` ShowLockOutFailures bool `json:"showLockOutFailures"` }