diff --git a/.gitignore b/.gitignore index 308614e2b8..8e5b5e4e02 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,5 @@ tmp/ console/src/app/proto/generated/ pkg/grpc/*/*.pb.* +pkg/grpc/*/mock/*.mock.go pkg/grpc/*/*.swagger.json \ No newline at end of file diff --git a/cmd/zitadel/startup.yaml b/cmd/zitadel/startup.yaml index 2d81a82c51..9f0f011d60 100644 --- a/cmd/zitadel/startup.yaml +++ b/cmd/zitadel/startup.yaml @@ -294,8 +294,4 @@ Notification: ConcurrentWorkers: 1 BulkLimit: 100 FailureCountUntilSkip: 5 - Handlers: - Notification: - MinimumCycleDuration: 5s - User: - MinimumCycleDuration: 5s \ No newline at end of file + Handlers: \ No newline at end of file diff --git a/internal/admin/repository/eventsourcing/eventstore/administrator.go b/internal/admin/repository/eventsourcing/eventstore/administrator.go index 52ab002cac..b36717481e 100644 --- a/internal/admin/repository/eventsourcing/eventstore/administrator.go +++ b/internal/admin/repository/eventsourcing/eventstore/administrator.go @@ -2,10 +2,11 @@ package eventstore import ( "context" + "time" + "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view" view_model "github.com/caos/zitadel/internal/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) var dbList = []string{"management", "auth", "authz", "adminapi", "notification"} @@ -47,7 +48,7 @@ func (repo *AdministratorRepo) GetViews() ([]*view_model.View, error) { } func (repo *AdministratorRepo) GetSpoolerDiv(database, view string) int64 { - sequence, err := repo.View.GetCurrentSequence(database, view) + sequence, err := repo.View.GetCurrentSequence(database, view, "") if err != nil { return 0 diff --git a/internal/admin/repository/eventsourcing/eventstore/iam.go b/internal/admin/repository/eventsourcing/eventstore/iam.go index 617cca2636..a08aad4b34 100644 --- a/internal/admin/repository/eventsourcing/eventstore/iam.go +++ b/internal/admin/repository/eventsourcing/eventstore/iam.go @@ -2,9 +2,10 @@ package eventstore import ( "context" - caos_errs "github.com/caos/zitadel/internal/errors" "strings" + caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/logging" admin_view "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view" "github.com/caos/zitadel/internal/config/systemdefaults" @@ -54,7 +55,7 @@ func (repo *IAMRepository) RemoveIAMMember(ctx context.Context, userID string) e func (repo *IAMRepository) SearchIAMMembers(ctx context.Context, request *iam_model.IAMMemberSearchRequest) (*iam_model.IAMMemberSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, err := repo.View.GetLatestIAMMemberSequence() + sequence, err := repo.View.GetLatestIAMMemberSequence("") logging.Log("EVENT-Slkci").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest iam sequence") members, count, err := repo.View.SearchIAMMembers(request) if err != nil { @@ -156,7 +157,7 @@ func (repo *IAMRepository) ChangeOidcIDPConfig(ctx context.Context, oidcConfig * func (repo *IAMRepository) SearchIDPConfigs(ctx context.Context, request *iam_model.IDPConfigSearchRequest) (*iam_model.IDPConfigSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, err := repo.View.GetLatestIDPConfigSequence() + sequence, err := repo.View.GetLatestIDPConfigSequence("") logging.Log("EVENT-Dk8si").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest idp config sequence") idps, count, err := repo.View.SearchIDPConfigs(request) if err != nil { @@ -248,7 +249,7 @@ func (repo *IAMRepository) ChangeDefaultLoginPolicy(ctx context.Context, policy func (repo *IAMRepository) SearchDefaultIDPProviders(ctx context.Context, request *iam_model.IDPProviderSearchRequest) (*iam_model.IDPProviderSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) request.AppendAggregateIDQuery(repo.SystemDefaults.IamID) - sequence, err := repo.View.GetLatestIDPProviderSequence() + sequence, err := repo.View.GetLatestIDPProviderSequence("") logging.Log("EVENT-Tuiks").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest iam sequence") providers, count, err := repo.View.SearchIDPProviders(request) if err != nil { diff --git a/internal/admin/repository/eventsourcing/eventstore/org.go b/internal/admin/repository/eventsourcing/eventstore/org.go index 78400eae29..59718f45be 100644 --- a/internal/admin/repository/eventsourcing/eventstore/org.go +++ b/internal/admin/repository/eventsourcing/eventstore/org.go @@ -87,7 +87,7 @@ func (repo *OrgRepo) OrgByID(ctx context.Context, id string) (*org_model.Org, er func (repo *OrgRepo) SearchOrgs(ctx context.Context, query *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, error) { query.EnsureLimit(repo.SearchLimit) - sequence, err := repo.View.GetLatestOrgSequence() + sequence, err := repo.View.GetLatestOrgSequence("") logging.Log("EVENT-LXo9w").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest iam sequence") orgs, count, err := repo.View.SearchOrgs(query) if err != nil { diff --git a/internal/admin/repository/eventsourcing/handler/handler.go b/internal/admin/repository/eventsourcing/handler/handler.go index 25f3b69223..60dcb9dac1 100644 --- a/internal/admin/repository/eventsourcing/handler/handler.go +++ b/internal/admin/repository/eventsourcing/handler/handler.go @@ -3,13 +3,12 @@ package handler import ( "time" - "github.com/caos/zitadel/internal/config/systemdefaults" - iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing" - "github.com/caos/zitadel/internal/admin/repository/eventsourcing/view" + "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/types" "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/query" + iam_event "github.com/caos/zitadel/internal/iam/repository/eventsourcing" org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing" usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing" ) @@ -25,6 +24,12 @@ type handler struct { bulkLimit uint64 cycleDuration time.Duration errorCountUntilSkip uint64 + + es eventstore.Eventstore +} + +func (h *handler) Eventstore() eventstore.Eventstore { + return h.es } type EventstoreRepos struct { @@ -33,31 +38,55 @@ type EventstoreRepos struct { OrgEvents *org_event.OrgEventstore } -func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, eventstore eventstore.Eventstore, repos EventstoreRepos, defaults systemdefaults.SystemDefaults) []query.Handler { +func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, defaults systemdefaults.SystemDefaults) []query.Handler { return []query.Handler{ - &Org{handler: handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount}}, - &IamMember{handler: handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount}, - userEvents: repos.UserEvents}, - &IDPConfig{handler: handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount}}, - &LabelPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount}}, - &LoginPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}}, - &IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount}, - systemDefaults: defaults, iamEvents: repos.IamEvents, orgEvents: repos.OrgEvents}, - &User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, - eventstore: eventstore, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, systemDefaults: defaults}, - &PasswordComplexityPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount}}, - &PasswordAgePolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordAgePolicy"), errorCount}}, - &PasswordLockoutPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordLockoutPolicy"), errorCount}}, - &OrgIAMPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount}}, - &ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount}, - orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, systemDefaults: defaults}, + newOrg( + handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}), + newIAMMember( + handler{view, bulkLimit, configs.cycleDuration("IamMember"), errorCount, es}, + repos.UserEvents), + newIDPConfig( + handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}), + newLabelPolicy( + handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount, es}), + newLoginPolicy( + handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount, es}), + newIDPProvider( + handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es}, + defaults, + repos.IamEvents, + repos.OrgEvents), + newUser( + handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es}, + repos.OrgEvents, + repos.IamEvents, + defaults), + newPasswordComplexityPolicy( + handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount, es}), + newPasswordAgePolicy( + handler{view, bulkLimit, configs.cycleDuration("PasswordAgePolicy"), errorCount, es}), + newPasswordLockoutPolicy( + handler{view, bulkLimit, configs.cycleDuration("PasswordLockoutPolicy"), errorCount, es}), + newOrgIAMPolicy( + handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}), + newExternalIDP( + handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es}, + defaults, + repos.IamEvents, + repos.OrgEvents), + } +} + +func subscribe(es eventstore.Eventstore, handlers []query.Handler) { + for _, handler := range handlers { + es.Subscribe(handler.AggregateTypes()...) } } func (configs Configs) cycleDuration(viewModel string) time.Duration { c, ok := configs[viewModel] if !ok { - return 1 * time.Second + return 3 * time.Minute } return c.MinimumCycleDuration.Duration } diff --git a/internal/admin/repository/eventsourcing/handler/iam_member.go b/internal/admin/repository/eventsourcing/handler/iam_member.go index 53d628b562..19db852e42 100644 --- a/internal/admin/repository/eventsourcing/handler/iam_member.go +++ b/internal/admin/repository/eventsourcing/handler/iam_member.go @@ -4,9 +4,9 @@ import ( "context" "github.com/caos/logging" - - "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" @@ -15,30 +15,63 @@ import ( usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" ) -type IamMember struct { - handler - userEvents *usr_event.UserEventstore -} - const ( iamMemberTable = "adminapi.iam_members" ) -func (m *IamMember) ViewModel() string { +type IAMMember struct { + handler + userEvents *usr_event.UserEventstore + subscription *eventstore.Subscription +} + +func newIAMMember(handler handler, userEvents *usr_event.UserEventstore) *IAMMember { + iamMember := &IAMMember{ + handler: handler, + userEvents: userEvents, + } + + iamMember.subscribe() + + return iamMember +} + +func (m *IAMMember) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + +func (m *IAMMember) CurrentSequence(event *es_models.Event) (uint64, error) { + sequence, err := m.view.GetLatestIAMMemberSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (m *IAMMember) ViewModel() string { return iamMemberTable } -func (m *IamMember) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestIAMMemberSequence() +func (m *IAMMember) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.IAMAggregate, usr_es_model.UserAggregate} +} + +func (m *IAMMember) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := m.view.GetLatestIAMMemberSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.IAMAggregate, usr_es_model.UserAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *IamMember) Reduce(event *models.Event) (err error) { +func (m *IAMMember) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate: err = m.processIamMember(event) @@ -48,7 +81,7 @@ func (m *IamMember) Reduce(event *models.Event) (err error) { return err } -func (m *IamMember) processIamMember(event *models.Event) (err error) { +func (m *IAMMember) processIamMember(event *es_models.Event) (err error) { member := new(iam_model.IAMMemberView) switch event.Type { case model.IAMMemberAdded: @@ -72,17 +105,17 @@ func (m *IamMember) processIamMember(event *models.Event) (err error) { if err != nil { return err } - return m.view.DeleteIAMMember(event.AggregateID, member.UserID, event.Sequence, event.CreationDate) + return m.view.DeleteIAMMember(event.AggregateID, member.UserID, event) default: - return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedIAMMemberSequence(event) } if err != nil { return err } - return m.view.PutIAMMember(member, member.Sequence, event.CreationDate) + return m.view.PutIAMMember(member, event) } -func (m *IamMember) processUser(event *models.Event) (err error) { +func (m *IAMMember) processUser(event *es_models.Event) (err error) { switch event.Type { case usr_es_model.UserProfileChanged, usr_es_model.UserEmailChanged, @@ -94,7 +127,7 @@ func (m *IamMember) processUser(event *models.Event) (err error) { return err } if len(members) == 0 { - return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedIAMMemberSequence(event) } user, err := m.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -103,15 +136,15 @@ func (m *IamMember) processUser(event *models.Event) (err error) { for _, member := range members { m.fillUserData(member, user) } - return m.view.PutIAMMembers(members, event.Sequence, event.CreationDate) + return m.view.PutIAMMembers(members, event) case usr_es_model.UserRemoved: - return m.view.DeleteIAMMembersByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteIAMMembersByUserID(event.AggregateID, event) default: - return m.view.ProcessedIAMMemberSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedIAMMemberSequence(event) } } -func (m *IamMember) fillData(member *iam_model.IAMMemberView) (err error) { +func (m *IAMMember) fillData(member *iam_model.IAMMemberView) (err error) { user, err := m.userEvents.UserByID(context.Background(), member.UserID) if err != nil { return err @@ -120,7 +153,7 @@ func (m *IamMember) fillData(member *iam_model.IAMMemberView) (err error) { return nil } -func (m *IamMember) fillUserData(member *iam_model.IAMMemberView, user *usr_model.User) { +func (m *IAMMember) fillUserData(member *iam_model.IAMMemberView, user *usr_model.User) { member.UserName = user.UserName if user.Human != nil { member.FirstName = user.FirstName @@ -132,11 +165,11 @@ func (m *IamMember) fillUserData(member *iam_model.IAMMemberView, user *usr_mode member.DisplayName = user.Machine.Name } } -func (m *IamMember) OnError(event *models.Event, err error) error { +func (m *IAMMember) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Ld9ow", "id", event.AggregateID).WithError(err).Warn("something went wrong in iammember handler") return spooler.HandleError(event, err, m.view.GetLatestIAMMemberFailedEvent, m.view.ProcessedIAMMemberFailedEvent, m.view.ProcessedIAMMemberSequence, m.errorCountUntilSkip) } -func (m *IamMember) OnSuccess() error { +func (m *IAMMember) OnSuccess() error { return spooler.HandleSuccess(m.view.UpdateIAMMemberSpoolerRunTimestamp) } diff --git a/internal/admin/repository/eventsourcing/handler/idp_config.go b/internal/admin/repository/eventsourcing/handler/idp_config.go index be8d43d7dc..bf0dc97104 100644 --- a/internal/admin/repository/eventsourcing/handler/idp_config.go +++ b/internal/admin/repository/eventsourcing/handler/idp_config.go @@ -2,38 +2,70 @@ package handler import ( "github.com/caos/logging" - iam_model "github.com/caos/zitadel/internal/iam/model" - - "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model" ) -type IDPConfig struct { - handler -} - const ( idpConfigTable = "adminapi.idp_configs" ) +type IDPConfig struct { + handler + subscription *eventstore.Subscription +} + +func newIDPConfig(handler handler) *IDPConfig { + h := &IDPConfig{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (i *IDPConfig) subscribe() { + i.subscription = i.es.Subscribe(i.AggregateTypes()...) + go func() { + for event := range i.subscription.Events { + query.ReduceEvent(i, event) + } + }() +} + func (i *IDPConfig) ViewModel() string { return idpConfigTable } -func (i *IDPConfig) EventQuery() (*models.SearchQuery, error) { - sequence, err := i.view.GetLatestIDPConfigSequence() +func (i *IDPConfig) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.IAMAggregate} +} + +func (i *IDPConfig) CurrentSequence(event *es_models.Event) (uint64, error) { + sequence, err := i.view.GetLatestIDPConfigSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (i *IDPConfig) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := i.view.GetLatestIDPConfigSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.IAMAggregate). + AggregateTypeFilter(i.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (i *IDPConfig) Reduce(event *models.Event) (err error) { +func (i *IDPConfig) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate: err = i.processIDPConfig(event) @@ -41,7 +73,7 @@ func (i *IDPConfig) Reduce(event *models.Event) (err error) { return err } -func (i *IDPConfig) processIDPConfig(event *models.Event) (err error) { +func (i *IDPConfig) processIDPConfig(event *es_models.Event) (err error) { idp := new(iam_view_model.IDPConfigView) switch event.Type { case model.IDPConfigAdded: @@ -63,17 +95,17 @@ func (i *IDPConfig) processIDPConfig(event *models.Event) (err error) { if err != nil { return err } - return i.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence, event.CreationDate) + return i.view.DeleteIDPConfig(idp.IDPConfigID, event) default: - return i.view.ProcessedIDPConfigSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedIDPConfigSequence(event) } if err != nil { return err } - return i.view.PutIDPConfig(idp, idp.Sequence, event.CreationDate) + return i.view.PutIDPConfig(idp, event) } -func (i *IDPConfig) OnError(event *models.Event, err error) error { +func (i *IDPConfig) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Mslo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp config handler") return spooler.HandleError(event, err, i.view.GetLatestIDPConfigFailedEvent, i.view.ProcessedIDPConfigFailedEvent, i.view.ProcessedIDPConfigSequence, i.errorCountUntilSkip) } diff --git a/internal/admin/repository/eventsourcing/handler/idp_providers.go b/internal/admin/repository/eventsourcing/handler/idp_providers.go index 0e27ee11ec..06c44c4c0a 100644 --- a/internal/admin/repository/eventsourcing/handler/idp_providers.go +++ b/internal/admin/repository/eventsourcing/handler/idp_providers.go @@ -2,18 +2,23 @@ package handler import ( "context" + "github.com/caos/logging" "github.com/caos/zitadel/internal/config/systemdefaults" - "github.com/caos/zitadel/internal/iam/repository/eventsourcing" - org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing" - org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" - - "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/zitadel/internal/iam/repository/eventsourcing" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model" + org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing" + org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" +) + +const ( + idpProviderTable = "adminapi.idp_providers" ) type IDPProvider struct { @@ -21,27 +26,63 @@ type IDPProvider struct { systemDefaults systemdefaults.SystemDefaults iamEvents *eventsourcing.IAMEventstore orgEvents *org_events.OrgEventstore + subscription *eventstore.Subscription } -const ( - idpProviderTable = "adminapi.idp_providers" -) +func newIDPProvider( + handler handler, + systemDefaults systemdefaults.SystemDefaults, + iamEvents *eventsourcing.IAMEventstore, + orgEvents *org_events.OrgEventstore, +) *IDPProvider { + h := &IDPProvider{ + handler: handler, + systemDefaults: systemDefaults, + iamEvents: iamEvents, + orgEvents: orgEvents, + } + + h.subscribe() + + return h +} + +func (i *IDPProvider) subscribe() { + i.subscription = i.es.Subscribe(i.AggregateTypes()...) + go func() { + for event := range i.subscription.Events { + query.ReduceEvent(i, event) + } + }() +} func (i *IDPProvider) ViewModel() string { return idpProviderTable } -func (i *IDPProvider) EventQuery() (*models.SearchQuery, error) { - sequence, err := i.view.GetLatestIDPProviderSequence() +func (i *IDPProvider) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.IAMAggregate, org_es_model.OrgAggregate} +} + +func (i *IDPProvider) CurrentSequence(event *es_models.Event) (uint64, error) { + sequence, err := i.view.GetLatestIDPProviderSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (i *IDPProvider) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := i.view.GetLatestIDPProviderSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.IAMAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(i.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (i *IDPProvider) Reduce(event *models.Event) (err error) { +func (i *IDPProvider) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate, org_es_model.OrgAggregate: err = i.processIdpProvider(event) @@ -49,7 +90,7 @@ func (i *IDPProvider) Reduce(event *models.Event) (err error) { return err } -func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) { +func (i *IDPProvider) processIdpProvider(event *es_models.Event) (err error) { provider := new(iam_view_model.IDPProviderView) switch event.Type { case model.LoginPolicyIDPProviderAdded, org_es_model.LoginPolicyIDPProviderAdded: @@ -64,7 +105,7 @@ func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) { if err != nil { return err } - return i.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence, event.CreationDate) + return i.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event) case model.IDPConfigChanged, org_es_model.IDPConfigChanged: esConfig := new(iam_view_model.IDPConfigView) providerType := iam_model.IDPProviderTypeSystem @@ -83,14 +124,14 @@ func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) { for _, provider := range providers { i.fillConfigData(provider, config) } - return i.view.PutIDPProviders(event.Sequence, event.CreationDate, providers...) + return i.view.PutIDPProviders(event, providers...) default: - return i.view.ProcessedIDPProviderSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedIDPProviderSequence(event) } if err != nil { return err } - return i.view.PutIDPProvider(provider, provider.Sequence, event.CreationDate) + return i.view.PutIDPProvider(provider, event) } func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) { @@ -114,7 +155,7 @@ func (i *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, c provider.IDPState = int32(config.State) } -func (i *IDPProvider) OnError(event *models.Event, err error) error { +func (i *IDPProvider) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Msj8c", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") return spooler.HandleError(event, err, i.view.GetLatestIDPProviderFailedEvent, i.view.ProcessedIDPProviderFailedEvent, i.view.ProcessedIDPProviderSequence, i.errorCountUntilSkip) } diff --git a/internal/admin/repository/eventsourcing/handler/label_policy.go b/internal/admin/repository/eventsourcing/handler/label_policy.go index 3f81c0060d..c1604fba69 100644 --- a/internal/admin/repository/eventsourcing/handler/label_policy.go +++ b/internal/admin/repository/eventsourcing/handler/label_policy.go @@ -2,37 +2,69 @@ package handler import ( "github.com/caos/logging" - - "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" ) -type LabelPolicy struct { - handler -} - const ( labelPolicyTable = "adminapi.label_policies" ) +type LabelPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newLabelPolicy(handler handler) *LabelPolicy { + h := &LabelPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *LabelPolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *LabelPolicy) ViewModel() string { return labelPolicyTable } -func (p *LabelPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestLabelPolicySequence() +func (p *LabelPolicy) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.IAMAggregate} +} + +func (p *LabelPolicy) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := p.view.GetLatestLabelPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (p *LabelPolicy) Reduce(event *models.Event) (err error) { +func (p *LabelPolicy) CurrentSequence(event *es_models.Event) (uint64, error) { + sequence, err := p.view.GetLatestLabelPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (p *LabelPolicy) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate: err = p.processLabelPolicy(event) @@ -40,7 +72,7 @@ func (p *LabelPolicy) Reduce(event *models.Event) (err error) { return err } -func (p *LabelPolicy) processLabelPolicy(event *models.Event) (err error) { +func (p *LabelPolicy) processLabelPolicy(event *es_models.Event) (err error) { policy := new(iam_model.LabelPolicyView) switch event.Type { case model.LabelPolicyAdded: @@ -52,15 +84,15 @@ func (p *LabelPolicy) processLabelPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) default: - return p.view.ProcessedLabelPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedLabelPolicySequence(event) } if err != nil { return err } - return p.view.PutLabelPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutLabelPolicy(policy, event) } -func (p *LabelPolicy) OnError(event *models.Event, err error) error { +func (p *LabelPolicy) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Wj8sf", "id", event.AggregateID).WithError(err).Warn("something went wrong in label policy handler") return spooler.HandleError(event, err, p.view.GetLatestLabelPolicyFailedEvent, p.view.ProcessedLabelPolicyFailedEvent, p.view.ProcessedLabelPolicySequence, p.errorCountUntilSkip) } diff --git a/internal/admin/repository/eventsourcing/handler/login_policy.go b/internal/admin/repository/eventsourcing/handler/login_policy.go index c24100ca69..032f2a4349 100644 --- a/internal/admin/repository/eventsourcing/handler/login_policy.go +++ b/internal/admin/repository/eventsourcing/handler/login_policy.go @@ -2,36 +2,69 @@ package handler import ( "github.com/caos/logging" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" ) -type LoginPolicy struct { - handler -} - const ( loginPolicyTable = "adminapi.login_policies" ) +type LoginPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newLoginPolicy(handler handler) *LoginPolicy { + h := &LoginPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *LoginPolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *LoginPolicy) ViewModel() string { return loginPolicyTable } +func (p *LoginPolicy) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.IAMAggregate} +} + func (p *LoginPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestLoginPolicySequence() + sequence, err := p.view.GetLatestLoginPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } +func (p *LoginPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestLoginPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *LoginPolicy) Reduce(event *models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate: @@ -56,12 +89,12 @@ func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) default: - return p.view.ProcessedLoginPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedLoginPolicySequence(event) } if err != nil { return err } - return p.view.PutLoginPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutLoginPolicy(policy, event) } func (p *LoginPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/admin/repository/eventsourcing/handler/org.go b/internal/admin/repository/eventsourcing/handler/org.go index eb64e60ea7..02ace32943 100644 --- a/internal/admin/repository/eventsourcing/handler/org.go +++ b/internal/admin/repository/eventsourcing/handler/org.go @@ -3,33 +3,67 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/org/repository/eventsourcing" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" org_model "github.com/caos/zitadel/internal/org/repository/view/model" ) -type Org struct { - handler -} - const ( orgTable = "adminapi.orgs" ) +type Org struct { + handler + subscription *eventstore.Subscription +} + +func newOrg(handler handler) *Org { + h := &Org{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (o *Org) subscribe() { + o.subscription = o.es.Subscribe(o.AggregateTypes()...) + go func() { + for event := range o.subscription.Events { + query.ReduceEvent(o, event) + } + }() +} + func (o *Org) ViewModel() string { return orgTable } +func (o *Org) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate} +} + func (o *Org) EventQuery() (*es_models.SearchQuery, error) { - sequence, err := o.view.GetLatestOrgSequence() + sequence, err := o.view.GetLatestOrgSequence("") if err != nil { return nil, err } return eventsourcing.OrgQuery(sequence.CurrentSequence), nil } +func (o *Org) CurrentSequence(event *es_models.Event) (uint64, error) { + sequence, err := o.view.GetLatestOrgSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (o *Org) Reduce(event *es_models.Event) error { org := new(org_model.OrgView) @@ -53,10 +87,10 @@ func (o *Org) Reduce(event *es_models.Event) error { return err } default: - return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate) + return o.view.ProcessedOrgSequence(event) } - return o.view.PutOrg(org, event.CreationDate) + return o.view.PutOrg(org, event) } func (o *Org) OnError(event *es_models.Event, spoolerErr error) error { diff --git a/internal/admin/repository/eventsourcing/handler/org_iam_policy.go b/internal/admin/repository/eventsourcing/handler/org_iam_policy.go index 99c01e73e1..a98db79c09 100644 --- a/internal/admin/repository/eventsourcing/handler/org_iam_policy.go +++ b/internal/admin/repository/eventsourcing/handler/org_iam_policy.go @@ -2,38 +2,70 @@ package handler import ( "github.com/caos/logging" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - - "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type OrgIAMPolicy struct { - handler -} - const ( orgIAMPolicyTable = "adminapi.org_iam_policies" ) +type OrgIAMPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newOrgIAMPolicy(handler handler) *OrgIAMPolicy { + h := &OrgIAMPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *OrgIAMPolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *OrgIAMPolicy) ViewModel() string { return orgIAMPolicyTable } -func (p *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestOrgIAMPolicySequence() +func (p *OrgIAMPolicy) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *OrgIAMPolicy) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := p.view.GetLatestOrgIAMPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (p *OrgIAMPolicy) Reduce(event *models.Event) (err error) { +func (p *OrgIAMPolicy) CurrentSequence(event *es_models.Event) (uint64, error) { + sequence, err := p.view.GetLatestOrgIAMPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (p *OrgIAMPolicy) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate, iam_es_model.IAMAggregate: err = p.processOrgIAMPolicy(event) @@ -41,7 +73,7 @@ func (p *OrgIAMPolicy) Reduce(event *models.Event) (err error) { return err } -func (p *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { +func (p *OrgIAMPolicy) processOrgIAMPolicy(event *es_models.Event) (err error) { policy := new(iam_model.OrgIAMPolicyView) switch event.Type { case iam_es_model.OrgIAMPolicyAdded, model.OrgIAMPolicyAdded: @@ -53,17 +85,17 @@ func (p *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) case model.OrgIAMPolicyRemoved: - return p.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence, event.CreationDate) + return p.view.DeleteOrgIAMPolicy(event.AggregateID, event) default: - return p.view.ProcessedOrgIAMPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedOrgIAMPolicySequence(event) } if err != nil { return err } - return p.view.PutOrgIAMPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutOrgIAMPolicy(policy, event) } -func (p *OrgIAMPolicy) OnError(event *models.Event, err error) error { +func (p *OrgIAMPolicy) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Wm8fs", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgIAM policy handler") return spooler.HandleError(event, err, p.view.GetLatestOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicySequence, p.errorCountUntilSkip) } diff --git a/internal/admin/repository/eventsourcing/handler/password_age_policy.go b/internal/admin/repository/eventsourcing/handler/password_age_policy.go index 3608ec446e..7cfa1b2bb2 100644 --- a/internal/admin/repository/eventsourcing/handler/password_age_policy.go +++ b/internal/admin/repository/eventsourcing/handler/password_age_policy.go @@ -2,34 +2,68 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type PasswordAgePolicy struct { - handler -} - const ( passwordAgePolicyTable = "adminapi.password_age_policies" ) +type PasswordAgePolicy struct { + handler + subscription *eventstore.Subscription +} + +func newPasswordAgePolicy(handler handler) *PasswordAgePolicy { + h := &PasswordAgePolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *PasswordAgePolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *PasswordAgePolicy) ViewModel() string { return passwordAgePolicyTable } +func (p *PasswordAgePolicy) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *PasswordAgePolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestPasswordAgePolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestPasswordAgePolicySequence() + sequence, err := p.view.GetLatestPasswordAgePolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -53,14 +87,14 @@ func (p *PasswordAgePolicy) processPasswordAgePolicy(event *models.Event) (err e } err = policy.AppendEvent(event) case model.PasswordAgePolicyRemoved: - return p.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence, event.CreationDate) + return p.view.DeletePasswordAgePolicy(event.AggregateID, event) default: - return p.view.ProcessedPasswordAgePolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedPasswordAgePolicySequence(event) } if err != nil { return err } - return p.view.PutPasswordAgePolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutPasswordAgePolicy(policy, event) } func (p *PasswordAgePolicy) OnError(event *models.Event, err error) error { diff --git a/internal/admin/repository/eventsourcing/handler/password_complexity_policy.go b/internal/admin/repository/eventsourcing/handler/password_complexity_policy.go index f1d2898218..edab685d23 100644 --- a/internal/admin/repository/eventsourcing/handler/password_complexity_policy.go +++ b/internal/admin/repository/eventsourcing/handler/password_complexity_policy.go @@ -2,34 +2,68 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type PasswordComplexityPolicy struct { - handler -} - const ( passwordComplexityPolicyTable = "adminapi.password_complexity_policies" ) +type PasswordComplexityPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newPasswordComplexityPolicy(handler handler) *PasswordComplexityPolicy { + h := &PasswordComplexityPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *PasswordComplexityPolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *PasswordComplexityPolicy) ViewModel() string { return passwordComplexityPolicyTable } +func (p *PasswordComplexityPolicy) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *PasswordComplexityPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestPasswordComplexityPolicySequence() + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -53,14 +87,14 @@ func (p *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models } err = policy.AppendEvent(event) case model.PasswordComplexityPolicyRemoved: - return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence, event.CreationDate) + return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event) default: - return p.view.ProcessedPasswordComplexityPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedPasswordComplexityPolicySequence(event) } if err != nil { return err } - return p.view.PutPasswordComplexityPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutPasswordComplexityPolicy(policy, event) } func (p *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/admin/repository/eventsourcing/handler/password_lockout_policy.go b/internal/admin/repository/eventsourcing/handler/password_lockout_policy.go index fd087adda7..99a8393cb8 100644 --- a/internal/admin/repository/eventsourcing/handler/password_lockout_policy.go +++ b/internal/admin/repository/eventsourcing/handler/password_lockout_policy.go @@ -2,34 +2,68 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type PasswordLockoutPolicy struct { - handler -} - const ( passwordLockoutPolicyTable = "adminapi.password_lockout_policies" ) +type PasswordLockoutPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newPasswordLockoutPolicy(handler handler) *PasswordLockoutPolicy { + h := &PasswordLockoutPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *PasswordLockoutPolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *PasswordLockoutPolicy) ViewModel() string { return passwordLockoutPolicyTable } +func (p *PasswordLockoutPolicy) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *PasswordLockoutPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestPasswordLockoutPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestPasswordLockoutPolicySequence() + sequence, err := p.view.GetLatestPasswordLockoutPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -53,14 +87,14 @@ func (p *PasswordLockoutPolicy) processPasswordLockoutPolicy(event *models.Event } err = policy.AppendEvent(event) case model.PasswordLockoutPolicyRemoved: - return p.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence, event.CreationDate) + return p.view.DeletePasswordLockoutPolicy(event.AggregateID, event) default: - return p.view.ProcessedPasswordLockoutPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedPasswordLockoutPolicySequence(event) } if err != nil { return err } - return p.view.PutPasswordLockoutPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutPasswordLockoutPolicy(policy, event) } func (p *PasswordLockoutPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/admin/repository/eventsourcing/handler/user.go b/internal/admin/repository/eventsourcing/handler/user.go index f0f26afc4f..eb3a4bd83f 100644 --- a/internal/admin/repository/eventsourcing/handler/user.go +++ b/internal/admin/repository/eventsourcing/handler/user.go @@ -2,6 +2,7 @@ package handler import ( "context" + "github.com/caos/zitadel/internal/config/systemdefaults" iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing" @@ -10,6 +11,7 @@ import ( "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" org_model "github.com/caos/zitadel/internal/org/model" org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing" @@ -18,29 +20,69 @@ import ( view_model "github.com/caos/zitadel/internal/user/repository/view/model" ) +const ( + userTable = "adminapi.users" +) + type User struct { handler eventstore eventstore.Eventstore orgEvents *org_events.OrgEventstore iamEvents *iam_es.IAMEventstore systemDefaults systemdefaults.SystemDefaults + subscription *eventstore.Subscription } -const ( - userTable = "adminapi.users" -) +func newUser( + handler handler, + orgEvents *org_events.OrgEventstore, + iamEvents *iam_es.IAMEventstore, + systemDefaults systemdefaults.SystemDefaults, +) *User { + h := &User{ + handler: handler, + orgEvents: orgEvents, + iamEvents: iamEvents, + systemDefaults: systemDefaults, + } + + h.subscribe() + + return h +} + +func (u *User) subscribe() { + u.subscription = u.es.Subscribe(u.AggregateTypes()...) + go func() { + for event := range u.subscription.Events { + query.ReduceEvent(u, event) + } + }() +} func (u *User) ViewModel() string { return userTable } +func (u *User) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.UserAggregate, org_es_model.OrgAggregate} +} + +func (u *User) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := u.view.GetLatestUserSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (u *User) EventQuery() (*models.SearchQuery, error) { - sequence, err := u.view.GetLatestUserSequence() + sequence, err := u.view.GetLatestUserSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(es_model.UserAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(u.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -116,14 +158,14 @@ func (u *User) ProcessUser(event *models.Event) (err error) { } err = u.fillLoginNames(user) case es_model.UserRemoved: - return u.view.DeleteUser(event.AggregateID, event.Sequence, event.CreationDate) + return u.view.DeleteUser(event.AggregateID, event) default: - return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserSequence(event) } if err != nil { return err } - return u.view.PutUser(user, user.Sequence, event.CreationDate) + return u.view.PutUser(user, event) } func (u *User) ProcessOrg(event *models.Event) (err error) { @@ -137,7 +179,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) { case org_es_model.OrgDomainPrimarySet: return u.fillPreferredLoginNamesOnOrgUsers(event) default: - return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserSequence(event) } } @@ -160,7 +202,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.SetLoginNames(policy, org.Domains) } - return u.view.PutUsers(users, event.Sequence, event.CreationDate) + return u.view.PutUsers(users, event) } func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { @@ -185,7 +227,7 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) } - return u.view.PutUsers(users, event.Sequence, event.CreationDate) + return u.view.PutUsers(users, event) } func (u *User) fillLoginNames(user *view_model.UserView) (err error) { diff --git a/internal/admin/repository/eventsourcing/handler/user_external_idps.go b/internal/admin/repository/eventsourcing/handler/user_external_idps.go index cc4d979dc3..cf4e4d05ce 100644 --- a/internal/admin/repository/eventsourcing/handler/user_external_idps.go +++ b/internal/admin/repository/eventsourcing/handler/user_external_idps.go @@ -2,9 +2,11 @@ package handler import ( "context" + "github.com/caos/logging" "github.com/caos/zitadel/internal/config/systemdefaults" caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/iam/repository/eventsourcing" iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model" org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing" @@ -14,33 +16,74 @@ import ( "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/model" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" ) +const ( + externalIDPTable = "adminapi.user_external_idps" +) + type ExternalIDP struct { handler systemDefaults systemdefaults.SystemDefaults iamEvents *eventsourcing.IAMEventstore orgEvents *org_es.OrgEventstore + subscription *eventstore.Subscription } -const ( - externalIDPTable = "adminapi.user_external_idps" -) +func newExternalIDP( + handler handler, + systemDefaults systemdefaults.SystemDefaults, + iamEvents *eventsourcing.IAMEventstore, + orgEvents *org_es.OrgEventstore, +) *ExternalIDP { + h := &ExternalIDP{ + handler: handler, + systemDefaults: systemDefaults, + iamEvents: iamEvents, + orgEvents: orgEvents, + } + + h.subscribe() + + return h +} + +func (i *ExternalIDP) subscribe() { + i.subscription = i.es.Subscribe(i.AggregateTypes()...) + go func() { + for event := range i.subscription.Events { + query.ReduceEvent(i, event) + } + }() +} func (i *ExternalIDP) ViewModel() string { return externalIDPTable } +func (i *ExternalIDP) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.UserAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate} +} + +func (i *ExternalIDP) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := i.view.GetLatestExternalIDPSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (i *ExternalIDP) EventQuery() (*models.SearchQuery, error) { - sequence, err := i.view.GetLatestExternalIDPSequence() + sequence, err := i.view.GetLatestExternalIDPSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.UserAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(i.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -68,16 +111,16 @@ func (i *ExternalIDP) processUser(event *models.Event) (err error) { if err != nil { return err } - return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence, event.CreationDate) + return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event) case model.UserRemoved: - return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event) default: - return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedExternalIDPSequence(event) } if err != nil { return err } - return i.view.PutExternalIDP(externalIDP, externalIDP.Sequence, event.CreationDate) + return i.view.PutExternalIDP(externalIDP, event) } func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { @@ -105,9 +148,9 @@ func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { for _, provider := range exterinalIDPs { i.fillConfigData(provider, config) } - return i.view.PutExternalIDPs(event.Sequence, event.CreationDate, exterinalIDPs...) + return i.view.PutExternalIDPs(event, exterinalIDPs...) default: - return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedExternalIDPSequence(event) } return nil } diff --git a/internal/admin/repository/eventsourcing/spooler/lock.go b/internal/admin/repository/eventsourcing/spooler/lock.go index 76317dc700..0c04a3bf07 100644 --- a/internal/admin/repository/eventsourcing/spooler/lock.go +++ b/internal/admin/repository/eventsourcing/spooler/lock.go @@ -3,8 +3,6 @@ package spooler import ( "database/sql" "time" - - es_locker "github.com/caos/zitadel/internal/eventstore/locker" ) const ( @@ -25,5 +23,5 @@ type lock struct { } func (l *locker) Renew(lockerID, viewModel string, waitTime time.Duration) error { - return es_locker.Renew(l.dbClient, lockTable, lockerID, viewModel, waitTime) + return nil } diff --git a/internal/admin/repository/eventsourcing/view/external_idps.go b/internal/admin/repository/eventsourcing/view/external_idps.go index 8f21e7de86..384c1d81d0 100644 --- a/internal/admin/repository/eventsourcing/view/external_idps.go +++ b/internal/admin/repository/eventsourcing/view/external_idps.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -33,44 +33,44 @@ func (v *View) SearchExternalIDPs(request *usr_model.ExternalIDPSearchRequest) ( return view.SearchExternalIDPs(v.Db, externalIDPTable, request) } -func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, event *models.Event) error { err := view.PutExternalIDP(v.Db, externalIDPTable, externalIDP) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) PutExternalIDPs(sequence uint64, eventTimestamp time.Time, externalIDPs ...*model.ExternalIDPView) error { +func (v *View) PutExternalIDPs(event *models.Event, externalIDPs ...*model.ExternalIDPView) error { err := view.PutExternalIDPs(v.Db, externalIDPTable, externalIDPs...) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, event *models.Event) error { err := view.DeleteExternalIDP(v.Db, externalIDPTable, externalUserID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteExternalIDPsByUserID(userID string, event *models.Event) error { err := view.DeleteExternalIDPsByUserID(v.Db, externalIDPTable, userID) if err != nil { return err } - return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) GetLatestExternalIDPSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(externalIDPTable) +func (v *View) GetLatestExternalIDPSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(externalIDPTable, aggregateType) } -func (v *View) ProcessedExternalIDPSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(externalIDPTable, eventSequence, eventTimestamp) +func (v *View) ProcessedExternalIDPSequence(event *models.Event) error { + return v.saveCurrentSequence(externalIDPTable, event) } func (v *View) UpdateExternalIDPSpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/iam_member.go b/internal/admin/repository/eventsourcing/view/iam_member.go index 250a0042fa..d215ca0b5b 100644 --- a/internal/admin/repository/eventsourcing/view/iam_member.go +++ b/internal/admin/repository/eventsourcing/view/iam_member.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -25,44 +25,44 @@ func (v *View) IAMMembersByUserID(userID string) ([]*model.IAMMemberView, error) return view.IAMMembersByUserID(v.Db, iamMemberTable, userID) } -func (v *View) PutIAMMember(org *model.IAMMemberView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutIAMMember(org *model.IAMMemberView, event *models.Event) error { err := view.PutIAMMember(v.Db, iamMemberTable, org) if err != nil { return err } - return v.ProcessedIAMMemberSequence(sequence, eventTimestamp) + return v.ProcessedIAMMemberSequence(event) } -func (v *View) PutIAMMembers(members []*model.IAMMemberView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutIAMMembers(members []*model.IAMMemberView, event *models.Event) error { err := view.PutIAMMembers(v.Db, iamMemberTable, members...) if err != nil { return err } - return v.ProcessedIAMMemberSequence(sequence, eventTimestamp) + return v.ProcessedIAMMemberSequence(event) } -func (v *View) DeleteIAMMember(iamID, userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIAMMember(iamID, userID string, event *models.Event) error { err := view.DeleteIAMMember(v.Db, iamMemberTable, iamID, userID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIAMMemberSequence(eventSequence, eventTimestamp) + return v.ProcessedIAMMemberSequence(event) } -func (v *View) DeleteIAMMembersByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIAMMembersByUserID(userID string, event *models.Event) error { err := view.DeleteIAMMembersByUserID(v.Db, iamMemberTable, userID) if err != nil { return err } - return v.ProcessedIAMMemberSequence(eventSequence, eventTimestamp) + return v.ProcessedIAMMemberSequence(event) } -func (v *View) GetLatestIAMMemberSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(iamMemberTable) +func (v *View) GetLatestIAMMemberSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(iamMemberTable, aggregateType) } -func (v *View) ProcessedIAMMemberSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(iamMemberTable, eventSequence, eventTimestamp) +func (v *View) ProcessedIAMMemberSequence(event *models.Event) error { + return v.saveCurrentSequence(iamMemberTable, event) } func (v *View) UpdateIAMMemberSpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/idp_configs.go b/internal/admin/repository/eventsourcing/view/idp_configs.go index 197c37d09b..5a120de265 100644 --- a/internal/admin/repository/eventsourcing/view/idp_configs.go +++ b/internal/admin/repository/eventsourcing/view/idp_configs.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -21,28 +21,28 @@ func (v *View) SearchIDPConfigs(request *iam_model.IDPConfigSearchRequest) ([]*m return view.SearchIDPs(v.Db, idpConfigTable, request) } -func (v *View) PutIDPConfig(idp *model.IDPConfigView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutIDPConfig(idp *model.IDPConfigView, event *models.Event) error { err := view.PutIDP(v.Db, idpConfigTable, idp) if err != nil { return err } - return v.ProcessedIDPConfigSequence(sequence, eventTimestamp) + return v.ProcessedIDPConfigSequence(event) } -func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIDPConfig(idpID string, event *models.Event) error { err := view.DeleteIDP(v.Db, idpConfigTable, idpID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPConfigSequence(eventSequence, eventTimestamp) + return v.ProcessedIDPConfigSequence(event) } -func (v *View) GetLatestIDPConfigSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(idpConfigTable) +func (v *View) GetLatestIDPConfigSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(idpConfigTable, aggregateType) } -func (v *View) ProcessedIDPConfigSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(idpConfigTable, eventSequence, eventTimestamp) +func (v *View) ProcessedIDPConfigSequence(event *models.Event) error { + return v.saveCurrentSequence(idpConfigTable, event) } func (v *View) UpdateIDPConfigSpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/idp_providers.go b/internal/admin/repository/eventsourcing/view/idp_providers.go index 10b5886945..26a682379d 100644 --- a/internal/admin/repository/eventsourcing/view/idp_providers.go +++ b/internal/admin/repository/eventsourcing/view/idp_providers.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -25,36 +25,36 @@ func (v *View) SearchIDPProviders(request *iam_model.IDPProviderSearchRequest) ( return view.SearchIDPProviders(v.Db, idpProviderTable, request) } -func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutIDPProvider(provider *model.IDPProviderView, event *models.Event) error { err := view.PutIDPProvider(v.Db, idpProviderTable, provider) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) PutIDPProviders(sequence uint64, eventTimestamp time.Time, providers ...*model.IDPProviderView) error { +func (v *View) PutIDPProviders(event *models.Event, providers ...*model.IDPProviderView) error { err := view.PutIDPProviders(v.Db, idpProviderTable, providers...) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, event *models.Event) error { err := view.DeleteIDPProvider(v.Db, idpProviderTable, aggregateID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) GetLatestIDPProviderSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(idpProviderTable) +func (v *View) GetLatestIDPProviderSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(idpProviderTable, aggregateType) } -func (v *View) ProcessedIDPProviderSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(idpProviderTable, eventSequence, eventTimestamp) +func (v *View) ProcessedIDPProviderSequence(event *models.Event) error { + return v.saveCurrentSequence(idpProviderTable, event) } func (v *View) UpdateIDPProviderSpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/label_policies.go b/internal/admin/repository/eventsourcing/view/label_policies.go index f4e921ac1c..9b1a46cee1 100644 --- a/internal/admin/repository/eventsourcing/view/label_policies.go +++ b/internal/admin/repository/eventsourcing/view/label_policies.go @@ -1,10 +1,10 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -15,20 +15,20 @@ func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyV return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID) } -func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error { err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy) if err != nil { return err } - return v.ProcessedLabelPolicySequence(sequence, eventTimestamp) + return v.ProcessedLabelPolicySequence(event) } -func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(labelPolicyTable) +func (v *View) GetLatestLabelPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(labelPolicyTable, aggregateType) } -func (v *View) ProcessedLabelPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(labelPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedLabelPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(labelPolicyTable, event) } func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/login_policies.go b/internal/admin/repository/eventsourcing/view/login_policies.go index 03e4451ffb..7e71983724 100644 --- a/internal/admin/repository/eventsourcing/view/login_policies.go +++ b/internal/admin/repository/eventsourcing/view/login_policies.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyV return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID) } -func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, event *models.Event) error { err := view.PutLoginPolicy(v.Db, loginPolicyTable, policy) if err != nil { return err } - return v.ProcessedLoginPolicySequence(sequence, eventTimestamp) + return v.ProcessedLoginPolicySequence(event) } -func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteLoginPolicy(aggregateID string, event *models.Event) error { err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedLoginPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedLoginPolicySequence(event) } -func (v *View) GetLatestLoginPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(loginPolicyTable) +func (v *View) GetLatestLoginPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(loginPolicyTable, aggregateType) } -func (v *View) ProcessedLoginPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(loginPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedLoginPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(loginPolicyTable, event) } func (v *View) UpdateLoginPolicySpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/org.go b/internal/admin/repository/eventsourcing/view/org.go index ee9f9fb113..b5d104a7ed 100644 --- a/internal/admin/repository/eventsourcing/view/org.go +++ b/internal/admin/repository/eventsourcing/view/org.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" org_model "github.com/caos/zitadel/internal/org/model" org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -20,12 +20,12 @@ func (v *View) SearchOrgs(query *org_model.OrgSearchRequest) ([]*model.OrgView, return org_view.SearchOrgs(v.Db, orgTable, query) } -func (v *View) PutOrg(org *model.OrgView, eventTimestamp time.Time) error { +func (v *View) PutOrg(org *model.OrgView, event *models.Event) error { err := org_view.PutOrg(v.Db, orgTable, org) if err != nil { return err } - return v.ProcessedOrgSequence(org.Sequence, eventTimestamp) + return v.ProcessedOrgSequence(event) } func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) { @@ -40,10 +40,10 @@ func (v *View) UpdateOrgSpoolerRunTimestamp() error { return v.updateSpoolerRunSequence(orgTable) } -func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(orgTable) +func (v *View) GetLatestOrgSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(orgTable, aggregateType) } -func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgSequence(event *models.Event) error { + return v.saveCurrentSequence(orgTable, event) } diff --git a/internal/admin/repository/eventsourcing/view/org_iam_policy.go b/internal/admin/repository/eventsourcing/view/org_iam_policy.go index 3168a78152..5d13779e48 100644 --- a/internal/admin/repository/eventsourcing/view/org_iam_policy.go +++ b/internal/admin/repository/eventsourcing/view/org_iam_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) OrgIAMPolicyByAggregateID(aggregateID string) (*model.OrgIAMPolic return view.GetOrgIAMPolicyByAggregateID(v.Db, orgIAMPolicyTable, aggregateID) } -func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, event *models.Event) error { err := view.PutOrgIAMPolicy(v.Db, orgIAMPolicyTable, policy) if err != nil { return err } - return v.ProcessedOrgIAMPolicySequence(sequence, eventTimestamp) + return v.ProcessedOrgIAMPolicySequence(event) } -func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteOrgIAMPolicy(aggregateID string, event *models.Event) error { err := view.DeleteOrgIAMPolicy(v.Db, orgIAMPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedOrgIAMPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedOrgIAMPolicySequence(event) } -func (v *View) GetLatestOrgIAMPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(orgIAMPolicyTable) +func (v *View) GetLatestOrgIAMPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(orgIAMPolicyTable, aggregateType) } -func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgIAMPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(orgIAMPolicyTable, event) } func (v *View) UpdateOrgIAMPolicySpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/password_age_policy.go b/internal/admin/repository/eventsourcing/view/password_age_policy.go index 419b537830..b1cbe535c4 100644 --- a/internal/admin/repository/eventsourcing/view/password_age_policy.go +++ b/internal/admin/repository/eventsourcing/view/password_age_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) PasswordAgePolicyByAggregateID(aggregateID string) (*model.Passwo return view.GetPasswordAgePolicyByAggregateID(v.Db, passwordAgePolicyTable, aggregateID) } -func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, event *models.Event) error { err := view.PutPasswordAgePolicy(v.Db, passwordAgePolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordAgePolicySequence(sequence, eventTimestamp) + return v.ProcessedPasswordAgePolicySequence(event) } -func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeletePasswordAgePolicy(aggregateID string, event *models.Event) error { err := view.DeletePasswordAgePolicy(v.Db, passwordAgePolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordAgePolicySequence(eventSequence, eventTimestamp) + return v.ProcessedPasswordAgePolicySequence(event) } -func (v *View) GetLatestPasswordAgePolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(passwordAgePolicyTable) +func (v *View) GetLatestPasswordAgePolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(passwordAgePolicyTable, aggregateType) } -func (v *View) ProcessedPasswordAgePolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(passwordAgePolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedPasswordAgePolicySequence(event *models.Event) error { + return v.saveCurrentSequence(passwordAgePolicyTable, event) } func (v *View) UpdateProcessedPasswordAgePolicySpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/password_complexity_policy.go b/internal/admin/repository/eventsourcing/view/password_complexity_policy.go index 2b1af7d375..44315b9666 100644 --- a/internal/admin/repository/eventsourcing/view/password_complexity_policy.go +++ b/internal/admin/repository/eventsourcing/view/password_complexity_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) PasswordComplexityPolicyByAggregateID(aggregateID string) (*model return view.GetPasswordComplexityPolicyByAggregateID(v.Db, passwordComplexityPolicyTable, aggregateID) } -func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, event *models.Event) error { err := view.PutPasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordComplexityPolicySequence(sequence, eventTimestamp) + return v.ProcessedPasswordComplexityPolicySequence(event) } -func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeletePasswordComplexityPolicy(aggregateID string, event *models.Event) error { err := view.DeletePasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordComplexityPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedPasswordComplexityPolicySequence(event) } -func (v *View) GetLatestPasswordComplexityPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(passwordComplexityPolicyTable) +func (v *View) GetLatestPasswordComplexityPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(passwordComplexityPolicyTable, aggregateType) } -func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedPasswordComplexityPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(passwordComplexityPolicyTable, event) } func (v *View) UpdatePasswordComplexityPolicySpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/password_lockout_policy.go b/internal/admin/repository/eventsourcing/view/password_lockout_policy.go index d20643d37c..805aab3fc3 100644 --- a/internal/admin/repository/eventsourcing/view/password_lockout_policy.go +++ b/internal/admin/repository/eventsourcing/view/password_lockout_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) PasswordLockoutPolicyByAggregateID(aggregateID string) (*model.Pa return view.GetPasswordLockoutPolicyByAggregateID(v.Db, passwordLockoutPolicyTable, aggregateID) } -func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, event *models.Event) error { err := view.PutPasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordLockoutPolicySequence(sequence, eventTimestamp) + return v.ProcessedPasswordLockoutPolicySequence(event) } -func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeletePasswordLockoutPolicy(aggregateID string, event *models.Event) error { err := view.DeletePasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordLockoutPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedPasswordLockoutPolicySequence(event) } -func (v *View) GetLatestPasswordLockoutPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(passwordLockoutPolicyTable) +func (v *View) GetLatestPasswordLockoutPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(passwordLockoutPolicyTable, aggregateType) } -func (v *View) ProcessedPasswordLockoutPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(passwordLockoutPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedPasswordLockoutPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(passwordLockoutPolicyTable, event) } func (v *View) UpdatePasswordLockoutPolicySpoolerRunTimestamp() error { diff --git a/internal/admin/repository/eventsourcing/view/sequence.go b/internal/admin/repository/eventsourcing/view/sequence.go index cda4580a6b..5915da9b56 100644 --- a/internal/admin/repository/eventsourcing/view/sequence.go +++ b/internal/admin/repository/eventsourcing/view/sequence.go @@ -1,20 +1,22 @@ package view import ( - "github.com/caos/zitadel/internal/view/repository" "time" + + "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/view/repository" ) const ( sequencesTable = "adminapi.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimeStamp time.Time) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimeStamp) +func (v *View) saveCurrentSequence(viewName string, event *models.Event) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, string(event.AggregateType), event.Sequence, event.CreationDate) } -func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { - return repository.LatestSequence(v.Db, sequencesTable, viewName) +func (v *View) latestSequence(viewName, aggregateType string) (*repository.CurrentSequence, error) { + return repository.LatestSequence(v.Db, sequencesTable, viewName, aggregateType) } func (v *View) AllCurrentSequences(db string) ([]*repository.CurrentSequence, error) { @@ -22,7 +24,7 @@ func (v *View) AllCurrentSequences(db string) ([]*repository.CurrentSequence, er } func (v *View) updateSpoolerRunSequence(viewName string) error { - currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName, "") if err != nil { return err } @@ -30,13 +32,16 @@ func (v *View) updateSpoolerRunSequence(viewName string) error { currentSequence.ViewName = viewName } currentSequence.LastSuccessfulSpoolerRun = time.Now() + //update all aggregate types + //TODO: not sure if all scenarios work as expected + currentSequence.AggregateType = "" return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) } -func (v *View) GetCurrentSequence(db, viewName string) (*repository.CurrentSequence, error) { +func (v *View) GetCurrentSequence(db, viewName, aggregateType string) (*repository.CurrentSequence, error) { sequenceTable := db + ".current_sequences" fullView := db + "." + viewName - return repository.LatestSequence(v.Db, sequenceTable, fullView) + return repository.LatestSequence(v.Db, sequenceTable, fullView, aggregateType) } func (v *View) ClearView(db, viewName string) error { diff --git a/internal/admin/repository/eventsourcing/view/user.go b/internal/admin/repository/eventsourcing/view/user.go index 3de68472cf..6e34155c96 100644 --- a/internal/admin/repository/eventsourcing/view/user.go +++ b/internal/admin/repository/eventsourcing/view/user.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -40,39 +40,39 @@ func (v *View) UserMFAs(userID string) ([]*usr_model.MultiFactor, error) { return view.UserMFAs(v.Db, userTable, userID) } -func (v *View) PutUsers(user []*model.UserView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUsers(user []*model.UserView, event *models.Event) error { err := view.PutUsers(v.Db, userTable, user...) if err != nil { return err } - return v.ProcessedUserSequence(sequence, eventTimestamp) + return v.ProcessedUserSequence(event) } -func (v *View) PutUser(user *model.UserView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUser(user *model.UserView, event *models.Event) error { err := view.PutUser(v.Db, userTable, user) if err != nil { return err } - if sequence != 0 { - return v.ProcessedUserSequence(sequence, eventTimestamp) + if event.Sequence != 0 { + return v.ProcessedUserSequence(event) } return nil } -func (v *View) DeleteUser(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUser(userID string, event *models.Event) error { err := view.DeleteUser(v.Db, userTable, userID) if err != nil { return nil } - return v.ProcessedUserSequence(eventSequence, eventTimestamp) + return v.ProcessedUserSequence(event) } -func (v *View) GetLatestUserSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userTable) +func (v *View) GetLatestUserSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userTable, aggregateType) } -func (v *View) ProcessedUserSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserSequence(event *models.Event) error { + return v.saveCurrentSequence(userTable, event) } func (v *View) UpdateUserSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/eventstore/org.go b/internal/auth/repository/eventsourcing/eventstore/org.go index c5f3ecced0..9339b1be70 100644 --- a/internal/auth/repository/eventsourcing/eventstore/org.go +++ b/internal/auth/repository/eventsourcing/eventstore/org.go @@ -36,7 +36,7 @@ type OrgRepository struct { func (repo *OrgRepository) SearchOrgs(ctx context.Context, request *org_model.OrgSearchRequest) (*org_model.OrgSearchResult, error) { request.EnsureLimit(repo.SearchLimit) - sequence, err := repo.View.GetLatestOrgSequence() + sequence, err := repo.View.GetLatestOrgSequence("") logging.Log("EVENT-7Udhz").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest org sequence") members, count, err := repo.View.SearchOrgs(request) if err != nil { diff --git a/internal/auth/repository/eventsourcing/eventstore/user.go b/internal/auth/repository/eventsourcing/eventstore/user.go index d4e96c32e3..392ff2a793 100644 --- a/internal/auth/repository/eventsourcing/eventstore/user.go +++ b/internal/auth/repository/eventsourcing/eventstore/user.go @@ -109,7 +109,7 @@ func (repo *UserRepo) ChangeMyProfile(ctx context.Context, profile *model.Profil func (repo *UserRepo) SearchMyExternalIDPs(ctx context.Context, request *model.ExternalIDPSearchRequest) (*model.ExternalIDPSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, seqErr := repo.View.GetLatestExternalIDPSequence() + sequence, seqErr := repo.View.GetLatestExternalIDPSequence("") logging.Log("EVENT-5Jsi8").OnError(seqErr).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest user sequence") request.AppendUserQuery(authz.GetCtxData(ctx).UserID) externalIDPS, count, err := repo.View.SearchExternalIDPs(request) diff --git a/internal/auth/repository/eventsourcing/eventstore/user_grant.go b/internal/auth/repository/eventsourcing/eventstore/user_grant.go index cba39e4314..d9ba6bc842 100644 --- a/internal/auth/repository/eventsourcing/eventstore/user_grant.go +++ b/internal/auth/repository/eventsourcing/eventstore/user_grant.go @@ -29,7 +29,7 @@ type UserGrantRepo struct { func (repo *UserGrantRepo) SearchMyUserGrants(ctx context.Context, request *grant_model.UserGrantSearchRequest) (*grant_model.UserGrantSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, err := repo.View.GetLatestUserGrantSequence() + sequence, err := repo.View.GetLatestUserGrantSequence("") logging.Log("EVENT-Hd7s3").OnError(err).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest user grant sequence") request.Queries = append(request.Queries, &grant_model.UserGrantSearchQuery{Key: grant_model.UserGrantSearchKeyUserID, Method: global_model.SearchMethodEquals, Value: authz.GetCtxData(ctx).UserID}) grants, count, err := repo.View.SearchUserGrants(request) diff --git a/internal/auth/repository/eventsourcing/handler/application.go b/internal/auth/repository/eventsourcing/handler/application.go index 377e0b0499..2ce66a2c22 100644 --- a/internal/auth/repository/eventsourcing/handler/application.go +++ b/internal/auth/repository/eventsourcing/handler/application.go @@ -5,7 +5,9 @@ import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/project/repository/eventsourcing" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" @@ -13,19 +15,52 @@ import ( view_model "github.com/caos/zitadel/internal/project/repository/view/model" ) -type Application struct { - handler - projectEvents *proj_event.ProjectEventstore -} - const ( applicationTable = "auth.applications" ) +type Application struct { + handler + projectEvents *proj_event.ProjectEventstore + subscription *eventstore.Subscription +} + +func newApplication(handler handler, projectEvents *proj_event.ProjectEventstore) *Application { + h := &Application{ + handler: handler, + projectEvents: projectEvents, + } + + h.subscribe() + + return h +} + +func (a *Application) subscribe() { + a.subscription = a.es.Subscribe(a.AggregateTypes()...) + go func() { + for event := range a.subscription.Events { + query.ReduceEvent(a, event) + } + }() +} + func (a *Application) ViewModel() string { return applicationTable } +func (_ *Application) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.ProjectAggregate} +} + +func (a *Application) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := a.view.GetLatestApplicationSequence() + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (a *Application) EventQuery() (*models.SearchQuery, error) { sequence, err := a.view.GetLatestApplicationSequence() if err != nil { @@ -65,30 +100,30 @@ func (a *Application) Reduce(event *models.Event) (err error) { if err != nil { return err } - return a.view.DeleteApplication(app.ID, event.Sequence, event.CreationDate) + return a.view.DeleteApplication(app.ID, event) case es_model.ProjectChanged: apps, err := a.view.ApplicationsByProjectID(event.AggregateID) if err != nil { return err } if len(apps) == 0 { - return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) + return a.view.ProcessedApplicationSequence(event) } for _, app := range apps { if err := app.AppendEvent(event); err != nil { return err } } - return a.view.PutApplications(apps, event.Sequence, event.CreationDate) + return a.view.PutApplications(apps, event) case es_model.ProjectRemoved: return a.view.DeleteApplicationsByProjectID(event.AggregateID) default: - return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) + return a.view.ProcessedApplicationSequence(event) } if err != nil { return err } - return a.view.PutApplication(app, event.CreationDate) + return a.view.PutApplication(app, event) } func (a *Application) OnError(event *models.Event, spoolerError error) error { diff --git a/internal/auth/repository/eventsourcing/handler/handler.go b/internal/auth/repository/eventsourcing/handler/handler.go index d641ec39db..0235304ce7 100644 --- a/internal/auth/repository/eventsourcing/handler/handler.go +++ b/internal/auth/repository/eventsourcing/handler/handler.go @@ -26,6 +26,12 @@ type handler struct { bulkLimit uint64 cycleDuration time.Duration errorCountUntilSkip uint64 + + es eventstore.Eventstore +} + +func (h *handler) Eventstore() eventstore.Eventstore { + return h.es } type EventstoreRepos struct { @@ -35,39 +41,65 @@ type EventstoreRepos struct { IamEvents *iam_events.IAMEventstore } -func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, eventstore eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults) []query.Handler { +func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults) []query.Handler { return []query.Handler{ - &User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, - orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, iamID: systemDefaults.IamID}, - &UserSession{handler: handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount}, userEvents: repos.UserEvents}, - &UserMembership{handler: handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount}, orgEvents: repos.OrgEvents, projectEvents: repos.ProjectEvents}, - &Token{handler: handler{view, bulkLimit, configs.cycleDuration("Token"), errorCount}, ProjectEvents: repos.ProjectEvents}, - &Key{handler: handler{view, bulkLimit, configs.cycleDuration("Key"), errorCount}}, - &Application{handler: handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount}, projectEvents: repos.ProjectEvents}, - &Org{handler: handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount}}, - &UserGrant{ - handler: handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount}, - eventstore: eventstore, - userEvents: repos.UserEvents, - orgEvents: repos.OrgEvents, - projectEvents: repos.ProjectEvents, - iamEvents: repos.IamEvents, - iamID: systemDefaults.IamID}, - &MachineKeys{handler: handler{view, bulkLimit, configs.cycleDuration("MachineKey"), errorCount}}, - &LoginPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}}, - &IDPConfig{handler: handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount}}, - &IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount}, systemDefaults: systemDefaults, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents}, - &ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount}, systemDefaults: systemDefaults, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents}, - &PasswordComplexityPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount}}, - &OrgIAMPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount}}, - &ProjectRole{handler: handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount}, projectEvents: repos.ProjectEvents}, + newUser( + handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es}, + repos.OrgEvents, + repos.IamEvents, + systemDefaults.IamID), + newUserSession( + handler{view, bulkLimit, configs.cycleDuration("UserSession"), errorCount, es}, + repos.UserEvents), + newUserMembership( + handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount, es}, + repos.OrgEvents, + repos.ProjectEvents), + newToken( + handler{view, bulkLimit, configs.cycleDuration("Token"), errorCount, es}, + repos.ProjectEvents), + newKey( + handler{view, bulkLimit, configs.cycleDuration("Key"), errorCount, es}), + newApplication(handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount, es}, + repos.ProjectEvents), + newOrg( + handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}), + newUserGrant( + handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount, es}, + repos.ProjectEvents, + repos.UserEvents, + repos.OrgEvents, + repos.IamEvents, + systemDefaults.IamID), + newMachineKeys( + handler{view, bulkLimit, configs.cycleDuration("MachineKey"), errorCount, es}), + newLoginPolicy( + handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount, es}), + newIDPConfig( + handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}), + newIDPProvider( + handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es}, + systemDefaults, + repos.IamEvents, + repos.OrgEvents), + newExternalIDP( + handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es}, + systemDefaults, + repos.IamEvents, + repos.OrgEvents), + newPasswordComplexityPolicy( + handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount, es}), + newOrgIAMPolicy( + handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}), + newProjectRole(handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount, es}, + repos.ProjectEvents), } } func (configs Configs) cycleDuration(viewModel string) time.Duration { c, ok := configs[viewModel] if !ok { - return 1 * time.Second + return 3 * time.Minute } return c.MinimumCycleDuration.Duration } diff --git a/internal/auth/repository/eventsourcing/handler/idp_config.go b/internal/auth/repository/eventsourcing/handler/idp_config.go index e6c21a6260..b070d89c8a 100644 --- a/internal/auth/repository/eventsourcing/handler/idp_config.go +++ b/internal/auth/repository/eventsourcing/handler/idp_config.go @@ -2,8 +2,10 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/model" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" @@ -11,25 +13,57 @@ import ( "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type IDPConfig struct { - handler -} - const ( idpConfigTable = "auth.idp_configs" ) +type IDPConfig struct { + handler + subscription *eventstore.Subscription +} + +func newIDPConfig(h handler) *IDPConfig { + idpConfig := &IDPConfig{ + handler: h, + } + + idpConfig.subscribe() + + return idpConfig +} + +func (i *IDPConfig) subscribe() { + i.subscription = i.es.Subscribe(i.AggregateTypes()...) + go func() { + for event := range i.subscription.Events { + query.ReduceEvent(i, event) + } + }() +} + func (i *IDPConfig) ViewModel() string { return idpConfigTable } +func (_ *IDPConfig) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (i *IDPConfig) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := i.view.GetLatestIDPConfigSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (i *IDPConfig) EventQuery() (*models.SearchQuery, error) { - sequence, err := i.view.GetLatestIDPConfigSequence() + sequence, err := i.view.GetLatestIDPConfigSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(i.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -66,14 +100,14 @@ func (i *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, eve if err != nil { return err } - return i.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence, event.CreationDate) + return i.view.DeleteIDPConfig(idp.IDPConfigID, event) default: - return i.view.ProcessedIDPConfigSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedIDPConfigSequence(event) } if err != nil { return err } - return i.view.PutIDPConfig(idp, idp.Sequence, event.CreationDate) + return i.view.PutIDPConfig(idp, event) } func (i *IDPConfig) OnError(event *models.Event, err error) error { diff --git a/internal/auth/repository/eventsourcing/handler/idp_providers.go b/internal/auth/repository/eventsourcing/handler/idp_providers.go index b92a20a3b4..8622fc57b1 100644 --- a/internal/auth/repository/eventsourcing/handler/idp_providers.go +++ b/internal/auth/repository/eventsourcing/handler/idp_providers.go @@ -2,42 +2,85 @@ package handler import ( "context" + "github.com/caos/logging" "github.com/caos/zitadel/internal/config/systemdefaults" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/iam/repository/eventsourcing" org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing" org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model" ) +const ( + idpProviderTable = "auth.idp_providers" +) + type IDPProvider struct { handler systemDefaults systemdefaults.SystemDefaults iamEvents *eventsourcing.IAMEventstore orgEvents *org_es.OrgEventstore + subscription *eventstore.Subscription } -const ( - idpProviderTable = "auth.idp_providers" -) +func newIDPProvider( + h handler, + defaults systemdefaults.SystemDefaults, + iamEvents *eventsourcing.IAMEventstore, + orgEvents *org_es.OrgEventstore, +) *IDPProvider { + idpProvider := &IDPProvider{ + handler: h, + systemDefaults: defaults, + iamEvents: iamEvents, + orgEvents: orgEvents, + } + + idpProvider.subscribe() + + return idpProvider +} + +func (i *IDPProvider) subscribe() { + i.subscription = i.es.Subscribe(i.AggregateTypes()...) + go func() { + for event := range i.subscription.Events { + query.ReduceEvent(i, event) + } + }() +} func (i *IDPProvider) ViewModel() string { return idpProviderTable } +func (_ *IDPProvider) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.IAMAggregate, org_es_model.OrgAggregate} +} + +func (i *IDPProvider) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := i.view.GetLatestIDPProviderSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (i *IDPProvider) EventQuery() (*models.SearchQuery, error) { - sequence, err := i.view.GetLatestIDPProviderSequence() + sequence, err := i.view.GetLatestIDPProviderSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.IAMAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(i.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -64,7 +107,7 @@ func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) { if err != nil { return err } - return i.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence, event.CreationDate) + return i.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event) case model.IDPConfigChanged, org_es_model.IDPConfigChanged: esConfig := new(iam_view_model.IDPConfigView) providerType := iam_model.IDPProviderTypeSystem @@ -88,16 +131,16 @@ func (i *IDPProvider) processIdpProvider(event *models.Event) (err error) { for _, provider := range providers { i.fillConfigData(provider, config) } - return i.view.PutIDPProviders(event.Sequence, event.CreationDate, providers...) + return i.view.PutIDPProviders(event, providers...) case org_es_model.LoginPolicyRemoved: - return i.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event.Sequence, event.CreationDate) + return i.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event) default: - return i.view.ProcessedIDPProviderSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedIDPProviderSequence(event) } if err != nil { return err } - return i.view.PutIDPProvider(provider, provider.Sequence, event.CreationDate) + return i.view.PutIDPProvider(provider, event) } func (i *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) { diff --git a/internal/auth/repository/eventsourcing/handler/key.go b/internal/auth/repository/eventsourcing/handler/key.go index 48f224cc29..54703a2509 100644 --- a/internal/auth/repository/eventsourcing/handler/key.go +++ b/internal/auth/repository/eventsourcing/handler/key.go @@ -3,30 +3,62 @@ package handler import ( "time" - es_model "github.com/caos/zitadel/internal/key/repository/eventsourcing/model" - "github.com/caos/logging" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/key/repository/eventsourcing" + es_model "github.com/caos/zitadel/internal/key/repository/eventsourcing/model" view_model "github.com/caos/zitadel/internal/key/repository/view/model" ) -type Key struct { - handler -} - const ( keyTable = "auth.keys" ) +type Key struct { + handler + subscription *eventstore.Subscription +} + +func newKey(handler handler) *Key { + h := &Key{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (k *Key) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (k *Key) ViewModel() string { return keyTable } +func (_ *Key) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.KeyPairAggregate} +} + +func (k *Key) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := k.view.GetLatestKeySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (k *Key) EventQuery() (*models.SearchQuery, error) { - sequence, err := k.view.GetLatestKeySequence() + sequence, err := k.view.GetLatestKeySequence("") if err != nil { return nil, err } @@ -41,11 +73,11 @@ func (k *Key) Reduce(event *models.Event) error { return err } if privateKey.Expiry.Before(time.Now()) && publicKey.Expiry.Before(time.Now()) { - return k.view.ProcessedKeySequence(event.Sequence, event.CreationDate) + return k.view.ProcessedKeySequence(event) } - return k.view.PutKeys(privateKey, publicKey, event.Sequence, event.CreationDate) + return k.view.PutKeys(privateKey, publicKey, event) default: - return k.view.ProcessedKeySequence(event.Sequence, event.CreationDate) + return k.view.ProcessedKeySequence(event) } } diff --git a/internal/auth/repository/eventsourcing/handler/login_policy.go b/internal/auth/repository/eventsourcing/handler/login_policy.go index b92dd17a9e..35700d80c7 100644 --- a/internal/auth/repository/eventsourcing/handler/login_policy.go +++ b/internal/auth/repository/eventsourcing/handler/login_policy.go @@ -2,34 +2,68 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type LoginPolicy struct { - handler -} - const ( loginPolicyTable = "auth.login_policies" ) +type LoginPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newLoginPolicy(handler handler) *LoginPolicy { + h := &LoginPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *LoginPolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *LoginPolicy) ViewModel() string { return loginPolicyTable } +func (_ *LoginPolicy) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *LoginPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestLoginPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *LoginPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestLoginPolicySequence() + sequence, err := p.view.GetLatestLoginPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -57,14 +91,14 @@ func (p *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) case model.LoginPolicyRemoved: - return p.view.DeleteLoginPolicy(event.AggregateID, event.Sequence, event.CreationDate) + return p.view.DeleteLoginPolicy(event.AggregateID, event) default: - return p.view.ProcessedLoginPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedLoginPolicySequence(event) } if err != nil { return err } - return p.view.PutLoginPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutLoginPolicy(policy, event) } func (p *LoginPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/auth/repository/eventsourcing/handler/machine_keys.go b/internal/auth/repository/eventsourcing/handler/machine_keys.go index f9af7e86fb..0ca0532c26 100644 --- a/internal/auth/repository/eventsourcing/handler/machine_keys.go +++ b/internal/auth/repository/eventsourcing/handler/machine_keys.go @@ -5,73 +5,107 @@ import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" usr_model "github.com/caos/zitadel/internal/user/repository/view/model" ) -type MachineKeys struct { - handler -} - const ( machineKeysTable = "auth.machine_keys" ) -func (d *MachineKeys) ViewModel() string { +type MachineKeys struct { + handler + subscription *eventstore.Subscription +} + +func newMachineKeys(handler handler) *MachineKeys { + h := &MachineKeys{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (k *MachineKeys) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + +func (k *MachineKeys) ViewModel() string { return machineKeysTable } -func (d *MachineKeys) EventQuery() (*models.SearchQuery, error) { - sequence, err := d.view.GetLatestMachineKeySequence() +func (_ *MachineKeys) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.UserAggregate} +} + +func (k *MachineKeys) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := k.view.GetLatestMachineKeySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (k *MachineKeys) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := k.view.GetLatestMachineKeySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.UserAggregate). + AggregateTypeFilter(k.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (d *MachineKeys) Reduce(event *models.Event) (err error) { +func (k *MachineKeys) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.UserAggregate: - err = d.processMachineKeys(event) + err = k.processMachineKeys(event) } return err } -func (d *MachineKeys) processMachineKeys(event *models.Event) (err error) { +func (k *MachineKeys) processMachineKeys(event *es_models.Event) (err error) { key := new(usr_model.MachineKeyView) switch event.Type { case model.MachineKeyAdded: err = key.AppendEvent(event) if key.ExpirationDate.Before(time.Now()) { - return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate) + return k.view.ProcessedMachineKeySequence(event) } case model.MachineKeyRemoved: err = key.SetData(event) if err != nil { return err } - return d.view.DeleteMachineKey(key.ID, event.Sequence, event.CreationDate) + return k.view.DeleteMachineKey(key.ID, event) case model.UserRemoved: - return d.view.DeleteMachineKeysByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return k.view.DeleteMachineKeysByUserID(event.AggregateID, event) default: - return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate) + return k.view.ProcessedMachineKeySequence(event) } if err != nil { return err } - return d.view.PutMachineKey(key, key.Sequence, event.CreationDate) + return k.view.PutMachineKey(key, event) } -func (d *MachineKeys) OnError(event *models.Event, err error) error { +func (k *MachineKeys) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-S9fe", "id", event.AggregateID).WithError(err).Warn("something went wrong in machine key handler") - return spooler.HandleError(event, err, d.view.GetLatestMachineKeyFailedEvent, d.view.ProcessedMachineKeyFailedEvent, d.view.ProcessedMachineKeySequence, d.errorCountUntilSkip) + return spooler.HandleError(event, err, k.view.GetLatestMachineKeyFailedEvent, k.view.ProcessedMachineKeyFailedEvent, k.view.ProcessedMachineKeySequence, k.errorCountUntilSkip) } -func (d *MachineKeys) OnSuccess() error { - return spooler.HandleSuccess(d.view.UpdateMachineKeySpoolerRunTimestamp) +func (k *MachineKeys) OnSuccess() error { + return spooler.HandleSuccess(k.view.UpdateMachineKeySpoolerRunTimestamp) } diff --git a/internal/auth/repository/eventsourcing/handler/org.go b/internal/auth/repository/eventsourcing/handler/org.go index 909cfefc4a..ea87eed2f2 100644 --- a/internal/auth/repository/eventsourcing/handler/org.go +++ b/internal/auth/repository/eventsourcing/handler/org.go @@ -3,27 +3,62 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" + "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/org/repository/eventsourcing" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" org_model "github.com/caos/zitadel/internal/org/repository/view/model" ) -type Org struct { - handler -} - const ( orgTable = "auth.orgs" ) +type Org struct { + handler + subscription *eventstore.Subscription +} + +func newOrg(handler handler) *Org { + h := &Org{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (o *Org) subscribe() { + o.subscription = o.es.Subscribe(o.AggregateTypes()...) + go func() { + for event := range o.subscription.Events { + query.ReduceEvent(o, event) + } + }() +} + func (o *Org) ViewModel() string { return orgTable } +func (_ *Org) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate} +} + +func (o *Org) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := o.view.GetLatestOrgSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (o *Org) EventQuery() (*es_models.SearchQuery, error) { - sequence, err := o.view.GetLatestOrgSequence() + sequence, err := o.view.GetLatestOrgSequence("") if err != nil { return nil, err } @@ -58,13 +93,13 @@ func (o *Org) Reduce(event *es_models.Event) (err error) { } org.Domain = domain.Domain default: - return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate) + return o.view.ProcessedOrgSequence(event) } if err != nil { return err } - return o.view.PutOrg(org, event.CreationDate) + return o.view.PutOrg(org, event) } func (o *Org) OnError(event *es_models.Event, spoolerErr error) error { diff --git a/internal/auth/repository/eventsourcing/handler/org_iam_policy.go b/internal/auth/repository/eventsourcing/handler/org_iam_policy.go index ac28b5c7c4..9d9d230a96 100644 --- a/internal/auth/repository/eventsourcing/handler/org_iam_policy.go +++ b/internal/auth/repository/eventsourcing/handler/org_iam_policy.go @@ -2,68 +2,101 @@ package handler import ( "github.com/caos/logging" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" - "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" + org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type OrgIAMPolicy struct { - handler -} - const ( orgIAMPolicyTable = "auth.org_iam_policies" ) +type OrgIAMPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newOrgIAMPolicy(handler handler) *OrgIAMPolicy { + h := &OrgIAMPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *OrgIAMPolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *OrgIAMPolicy) ViewModel() string { return orgIAMPolicyTable } -func (p *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestOrgIAMPolicySequence() +func (_ *OrgIAMPolicy) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{org_es_model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *OrgIAMPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestOrgIAMPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (p *OrgIAMPolicy) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := p.view.GetLatestOrgIAMPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (p *OrgIAMPolicy) Reduce(event *models.Event) (err error) { +func (p *OrgIAMPolicy) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { - case model.OrgAggregate, iam_es_model.IAMAggregate: + case org_es_model.OrgAggregate, iam_es_model.IAMAggregate: err = p.processOrgIAMPolicy(event) } return err } -func (p *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { +func (p *OrgIAMPolicy) processOrgIAMPolicy(event *es_models.Event) (err error) { policy := new(iam_model.OrgIAMPolicyView) switch event.Type { - case iam_es_model.OrgIAMPolicyAdded, model.OrgIAMPolicyAdded: + case iam_es_model.OrgIAMPolicyAdded, org_es_model.OrgIAMPolicyAdded: err = policy.AppendEvent(event) - case iam_es_model.OrgIAMPolicyChanged, model.OrgIAMPolicyChanged: + case iam_es_model.OrgIAMPolicyChanged, org_es_model.OrgIAMPolicyChanged: policy, err = p.view.OrgIAMPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) - case model.OrgIAMPolicyRemoved: - return p.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence, event.CreationDate) + case org_es_model.OrgIAMPolicyRemoved: + return p.view.DeleteOrgIAMPolicy(event.AggregateID, event) default: - return p.view.ProcessedOrgIAMPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedOrgIAMPolicySequence(event) } if err != nil { return err } - return p.view.PutOrgIAMPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutOrgIAMPolicy(policy, event) } -func (p *OrgIAMPolicy) OnError(event *models.Event, err error) error { +func (p *OrgIAMPolicy) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-3Gj8s", "id", event.AggregateID).WithError(err).Warn("something went wrong in orgIAM policy handler") return spooler.HandleError(event, err, p.view.GetLatestOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicyFailedEvent, p.view.ProcessedOrgIAMPolicySequence, p.errorCountUntilSkip) } diff --git a/internal/auth/repository/eventsourcing/handler/password_complexity_policy.go b/internal/auth/repository/eventsourcing/handler/password_complexity_policy.go index d3656a164a..65a86676a8 100644 --- a/internal/auth/repository/eventsourcing/handler/password_complexity_policy.go +++ b/internal/auth/repository/eventsourcing/handler/password_complexity_policy.go @@ -2,68 +2,101 @@ package handler import ( "github.com/caos/logging" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" - "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" + org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type PasswordComplexityPolicy struct { - handler -} - const ( passwordComplexityPolicyTable = "auth.password_complexity_policies" ) +type PasswordComplexityPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newPasswordComplexityPolicy(handler handler) *PasswordComplexityPolicy { + h := &PasswordComplexityPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (p *PasswordComplexityPolicy) subscribe() { + p.subscription = p.es.Subscribe(p.AggregateTypes()...) + go func() { + for event := range p.subscription.Events { + query.ReduceEvent(p, event) + } + }() +} + func (p *PasswordComplexityPolicy) ViewModel() string { return passwordComplexityPolicyTable } -func (p *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestPasswordComplexityPolicySequence() +func (_ *PasswordComplexityPolicy) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{org_es_model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *PasswordComplexityPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (p *PasswordComplexityPolicy) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (p *PasswordComplexityPolicy) Reduce(event *models.Event) (err error) { +func (p *PasswordComplexityPolicy) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { - case model.OrgAggregate, iam_es_model.IAMAggregate: + case org_es_model.OrgAggregate, iam_es_model.IAMAggregate: err = p.processPasswordComplexityPolicy(event) } return err } -func (p *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models.Event) (err error) { +func (p *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *es_models.Event) (err error) { policy := new(iam_model.PasswordComplexityPolicyView) switch event.Type { - case iam_es_model.PasswordComplexityPolicyAdded, model.PasswordComplexityPolicyAdded: + case iam_es_model.PasswordComplexityPolicyAdded, org_es_model.PasswordComplexityPolicyAdded: err = policy.AppendEvent(event) - case iam_es_model.PasswordComplexityPolicyChanged, model.PasswordComplexityPolicyChanged: + case iam_es_model.PasswordComplexityPolicyChanged, org_es_model.PasswordComplexityPolicyChanged: policy, err = p.view.PasswordComplexityPolicyByAggregateID(event.AggregateID) if err != nil { return err } err = policy.AppendEvent(event) - case model.PasswordComplexityPolicyRemoved: - return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence, event.CreationDate) + case org_es_model.PasswordComplexityPolicyRemoved: + return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event) default: - return p.view.ProcessedPasswordComplexityPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedPasswordComplexityPolicySequence(event) } if err != nil { return err } - return p.view.PutPasswordComplexityPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutPasswordComplexityPolicy(policy, event) } -func (p *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { +func (p *PasswordComplexityPolicy) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-4Djo9", "id", event.AggregateID).WithError(err).Warn("something went wrong in passwordComplexity policy handler") return spooler.HandleError(event, err, p.view.GetLatestPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicyFailedEvent, p.view.ProcessedPasswordComplexityPolicySequence, p.errorCountUntilSkip) } diff --git a/internal/auth/repository/eventsourcing/handler/project_role.go b/internal/auth/repository/eventsourcing/handler/project_role.go index c469019b9f..9d7e684c7c 100644 --- a/internal/auth/repository/eventsourcing/handler/project_role.go +++ b/internal/auth/repository/eventsourcing/handler/project_role.go @@ -3,41 +3,80 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" - "github.com/caos/zitadel/internal/project/repository/eventsourcing" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" - es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" + proj_events "github.com/caos/zitadel/internal/project/repository/eventsourcing" + "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" view_model "github.com/caos/zitadel/internal/project/repository/view/model" ) -type ProjectRole struct { - handler - projectEvents *proj_event.ProjectEventstore -} - const ( projectRoleTable = "auth.project_roles" ) +type ProjectRole struct { + handler + projectEvents *proj_event.ProjectEventstore + subscription *eventstore.Subscription +} + +func newProjectRole( + handler handler, + projectEvents *proj_events.ProjectEventstore, +) *ProjectRole { + h := &ProjectRole{ + handler: handler, + projectEvents: projectEvents, + } + + h.subscribe() + + return h +} + +func (k *ProjectRole) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (p *ProjectRole) ViewModel() string { return projectRoleTable } -func (p *ProjectRole) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestProjectRoleSequence() +func (_ *ProjectRole) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.ProjectAggregate} +} + +func (p *ProjectRole) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestProjectRoleSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (p *ProjectRole) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := p.view.GetLatestProjectRoleSequence("") if err != nil { return nil, err } - return eventsourcing.ProjectQuery(sequence.CurrentSequence), nil + return proj_events.ProjectQuery(sequence.CurrentSequence), nil } -func (p *ProjectRole) Reduce(event *models.Event) (err error) { +func (p *ProjectRole) Reduce(event *es_models.Event) (err error) { role := new(view_model.ProjectRoleView) switch event.Type { - case es_model.ProjectRoleAdded: + case model.ProjectRoleAdded: err = role.AppendEvent(event) - case es_model.ProjectRoleChanged: + case model.ProjectRoleChanged: err = role.SetData(event) if err != nil { return err @@ -47,24 +86,24 @@ func (p *ProjectRole) Reduce(event *models.Event) (err error) { return err } err = role.AppendEvent(event) - case es_model.ProjectRoleRemoved: + case model.ProjectRoleRemoved: err = role.SetData(event) if err != nil { return err } - return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence, event.CreationDate) - case es_model.ProjectRemoved: + return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event) + case model.ProjectRemoved: return p.view.DeleteProjectRolesByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectRoleSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectRoleSequence(event) } if err != nil { return err } - return p.view.PutProjectRole(role, event.CreationDate) + return p.view.PutProjectRole(role, event) } -func (p *ProjectRole) OnError(event *models.Event, err error) error { +func (p *ProjectRole) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-lso9w", "id", event.AggregateID).WithError(err).Warn("something went wrong in project role handler") return spooler.HandleError(event, err, p.view.GetLatestProjectRoleFailedEvent, p.view.ProcessedProjectRoleFailedEvent, p.view.ProcessedProjectRoleSequence, p.errorCountUntilSkip) } diff --git a/internal/auth/repository/eventsourcing/handler/token.go b/internal/auth/repository/eventsourcing/handler/token.go index 2c056cc064..b98e811bda 100644 --- a/internal/auth/repository/eventsourcing/handler/token.go +++ b/internal/auth/repository/eventsourcing/handler/token.go @@ -6,8 +6,10 @@ import ( "github.com/caos/logging" caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" project_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" @@ -15,21 +17,57 @@ import ( view_model "github.com/caos/zitadel/internal/user/repository/view/model" ) -type Token struct { - handler - ProjectEvents *proj_event.ProjectEventstore -} - const ( tokenTable = "auth.tokens" ) +type Token struct { + handler + ProjectEvents *proj_event.ProjectEventstore + subscription *eventstore.Subscription +} + +func newToken( + handler handler, + projectEvents *proj_event.ProjectEventstore, +) *Token { + h := &Token{ + handler: handler, + ProjectEvents: projectEvents, + } + + h.subscribe() + + return h +} + +func (t *Token) subscribe() { + t.subscription = t.es.Subscribe(t.AggregateTypes()...) + go func() { + for event := range t.subscription.Events { + query.ReduceEvent(t, event) + } + }() +} + func (t *Token) ViewModel() string { return tokenTable } +func (_ *Token) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{user_es_model.UserAggregate, project_es_model.ProjectAggregate} +} + +func (p *Token) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestTokenSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (t *Token) EventQuery() (*models.SearchQuery, error) { - sequence, err := t.view.GetLatestTokenSequence() + sequence, err := t.view.GetLatestTokenSequence("") if err != nil { return nil, err } @@ -49,7 +87,7 @@ func (t *Token) Reduce(event *models.Event) (err error) { if err != nil { return err } - return t.view.PutToken(token, event.CreationDate) + return t.view.PutToken(token, event) case user_es_model.UserProfileChanged, user_es_model.HumanProfileChanged: user := new(view_model.UserView) @@ -61,25 +99,25 @@ func (t *Token) Reduce(event *models.Event) (err error) { for _, token := range tokens { token.PreferredLanguage = user.PreferredLanguage } - return t.view.PutTokens(tokens, event.Sequence, event.CreationDate) + return t.view.PutTokens(tokens, event) case user_es_model.SignedOut, user_es_model.HumanSignedOut: id, err := agentIDFromSession(event) if err != nil { return err } - return t.view.DeleteSessionTokens(id, event.AggregateID, event.Sequence, event.CreationDate) + return t.view.DeleteSessionTokens(id, event.AggregateID, event) case user_es_model.UserLocked, user_es_model.UserDeactivated, user_es_model.UserRemoved: - return t.view.DeleteUserTokens(event.AggregateID, event.Sequence, event.CreationDate) + return t.view.DeleteUserTokens(event.AggregateID, event) case project_es_model.ApplicationDeactivated, project_es_model.ApplicationRemoved: application, err := applicationFromSession(event) if err != nil { return err } - return t.view.DeleteApplicationTokens(event.Sequence, event.CreationDate, application.AppID) + return t.view.DeleteApplicationTokens(event, application.AppID) case project_es_model.ProjectDeactivated, project_es_model.ProjectRemoved: project, err := t.ProjectEvents.ProjectByID(context.Background(), event.AggregateID) @@ -90,9 +128,9 @@ func (t *Token) Reduce(event *models.Event) (err error) { for _, app := range project.Applications { applicationsIDs = append(applicationsIDs, app.AppID) } - return t.view.DeleteApplicationTokens(event.Sequence, event.CreationDate, applicationsIDs...) + return t.view.DeleteApplicationTokens(event, applicationsIDs...) default: - return t.view.ProcessedTokenSequence(event.Sequence, event.CreationDate) + return t.view.ProcessedTokenSequence(event) } } diff --git a/internal/auth/repository/eventsourcing/handler/user.go b/internal/auth/repository/eventsourcing/handler/user.go index 8b1ceb091c..f960ab720d 100644 --- a/internal/auth/repository/eventsourcing/handler/user.go +++ b/internal/auth/repository/eventsourcing/handler/user.go @@ -2,45 +2,83 @@ package handler import ( "context" - iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing" + "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" + "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" + "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing" org_model "github.com/caos/zitadel/internal/org/model" org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing" org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" - - "github.com/caos/logging" - - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/eventstore/models" - "github.com/caos/zitadel/internal/eventstore/spooler" view_model "github.com/caos/zitadel/internal/user/repository/view/model" ) -type User struct { - handler - eventstore eventstore.Eventstore - orgEvents *org_events.OrgEventstore - iamEvents *iam_es.IAMEventstore - iamID string -} - const ( userTable = "auth.users" ) +type User struct { + handler + orgEvents *org_events.OrgEventstore + iamEvents *iam_es.IAMEventstore + iamID string + subscription *eventstore.Subscription +} + +func newUser( + handler handler, + orgEvents *org_events.OrgEventstore, + iamEvents *iam_es.IAMEventstore, + iamID string, +) *User { + h := &User{ + handler: handler, + orgEvents: orgEvents, + iamEvents: iamEvents, + iamID: iamID, + } + + h.subscribe() + + return h +} + +func (k *User) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (u *User) ViewModel() string { return userTable } +func (_ *User) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.UserAggregate, org_es_model.OrgAggregate} +} + +func (u *User) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := u.view.GetLatestUserSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (u *User) EventQuery() (*models.SearchQuery, error) { - sequence, err := u.view.GetLatestUserSequence() + sequence, err := u.view.GetLatestUserSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(es_model.UserAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(u.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -120,14 +158,14 @@ func (u *User) ProcessUser(event *models.Event) (err error) { } err = u.fillLoginNames(user) case es_model.UserRemoved: - return u.view.DeleteUser(event.AggregateID, event.Sequence, event.CreationDate) + return u.view.DeleteUser(event.AggregateID, event) default: - return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserSequence(event) } if err != nil { return err } - return u.view.PutUser(user, user.Sequence, event.CreationDate) + return u.view.PutUser(user, event) } func (u *User) fillLoginNames(user *view_model.UserView) (err error) { @@ -158,7 +196,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) { case org_es_model.OrgDomainPrimarySet: return u.fillPreferredLoginNamesOnOrgUsers(event) default: - return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserSequence(event) } } @@ -181,7 +219,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.SetLoginNames(policy, org.Domains) } - return u.view.PutUsers(users, event.Sequence, event.CreationDate) + return u.view.PutUsers(users, event) } func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { @@ -206,7 +244,7 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) } - return u.view.PutUsers(users, 0, event.CreationDate) + return u.view.PutUsers(users, event) } func (u *User) OnError(event *models.Event, err error) error { diff --git a/internal/auth/repository/eventsourcing/handler/user_external_idps.go b/internal/auth/repository/eventsourcing/handler/user_external_idps.go index 826d79170c..8dcaebe3cb 100644 --- a/internal/auth/repository/eventsourcing/handler/user_external_idps.go +++ b/internal/auth/repository/eventsourcing/handler/user_external_idps.go @@ -2,11 +2,14 @@ package handler import ( "context" + "github.com/caos/logging" "github.com/caos/zitadel/internal/config/systemdefaults" caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/eventsourcing" @@ -18,28 +21,68 @@ import ( usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model" ) +const ( + externalIDPTable = "auth.user_external_idps" +) + type ExternalIDP struct { handler systemDefaults systemdefaults.SystemDefaults iamEvents *eventsourcing.IAMEventstore orgEvents *org_es.OrgEventstore + subscription *eventstore.Subscription } -const ( - externalIDPTable = "auth.user_external_idps" -) +func newExternalIDP( + handler handler, + defaults systemdefaults.SystemDefaults, + iamEvents *eventsourcing.IAMEventstore, + orgEvents *org_es.OrgEventstore, +) *ExternalIDP { + h := &ExternalIDP{ + handler: handler, + systemDefaults: defaults, + iamEvents: iamEvents, + orgEvents: orgEvents, + } + + h.subscribe() + + return h +} + +func (i *ExternalIDP) subscribe() { + i.subscription = i.es.Subscribe(i.AggregateTypes()...) + go func() { + for event := range i.subscription.Events { + query.ReduceEvent(i, event) + } + }() +} func (i *ExternalIDP) ViewModel() string { return externalIDPTable } +func (_ *ExternalIDP) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.UserAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate} +} + +func (i *ExternalIDP) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := i.view.GetLatestExternalIDPSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (i *ExternalIDP) EventQuery() (*models.SearchQuery, error) { - sequence, err := i.view.GetLatestExternalIDPSequence() + sequence, err := i.view.GetLatestExternalIDPSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.UserAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(i.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -67,16 +110,16 @@ func (i *ExternalIDP) processUser(event *models.Event) (err error) { if err != nil { return err } - return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence, event.CreationDate) + return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event) case model.UserRemoved: - return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event) default: - return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedExternalIDPSequence(event) } if err != nil { return err } - return i.view.PutExternalIDP(externalIDP, externalIDP.Sequence, event.CreationDate) + return i.view.PutExternalIDP(externalIDP, event) } func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { @@ -104,9 +147,9 @@ func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { for _, provider := range exterinalIDPs { i.fillConfigData(provider, config) } - return i.view.PutExternalIDPs(event.Sequence, event.CreationDate, exterinalIDPs...) + return i.view.PutExternalIDPs(event, exterinalIDPs...) default: - return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedExternalIDPSequence(event) } return nil } diff --git a/internal/auth/repository/eventsourcing/handler/user_grant.go b/internal/auth/repository/eventsourcing/handler/user_grant.go index c61f831162..c2288891ce 100644 --- a/internal/auth/repository/eventsourcing/handler/user_grant.go +++ b/internal/auth/repository/eventsourcing/handler/user_grant.go @@ -10,6 +10,7 @@ import ( "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "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" @@ -27,25 +28,68 @@ import ( view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model" ) +const ( + userGrantTable = "auth.user_grants" +) + type UserGrant struct { handler - eventstore eventstore.Eventstore projectEvents *proj_event.ProjectEventstore userEvents *usr_events.UserEventstore orgEvents *org_events.OrgEventstore iamEvents *iam_events.IAMEventstore iamID string iamProjectID string + subscription *eventstore.Subscription } -const ( - userGrantTable = "auth.user_grants" -) +func newUserGrant( + handler handler, + projectEvents *proj_event.ProjectEventstore, + userEvents *usr_events.UserEventstore, + orgEvents *org_events.OrgEventstore, + iamEvents *iam_events.IAMEventstore, + iamID string, +) *UserGrant { + h := &UserGrant{ + handler: handler, + projectEvents: projectEvents, + userEvents: userEvents, + orgEvents: orgEvents, + iamEvents: iamEvents, + iamID: iamID, + } + + h.subscribe() + + return h +} + +func (k *UserGrant) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} func (u *UserGrant) ViewModel() string { return userGrantTable } +func (_ *UserGrant) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{grant_es_model.UserGrantAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate, usr_es_model.UserAggregate, proj_es_model.ProjectAggregate} +} + +func (u *UserGrant) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := u.view.GetLatestUserGrantSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (u *UserGrant) EventQuery() (*models.SearchQuery, error) { if u.iamProjectID == "" { err := u.setIamProjectID() @@ -53,12 +97,12 @@ func (u *UserGrant) EventQuery() (*models.SearchQuery, error) { return nil, err } } - sequence, err := u.view.GetLatestUserGrantSequence() + sequence, err := u.view.GetLatestUserGrantSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(grant_es_model.UserGrantAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate, usr_es_model.UserAggregate, proj_es_model.ProjectAggregate). + AggregateTypeFilter(u.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -97,14 +141,14 @@ func (u *UserGrant) processUserGrant(event *models.Event) (err error) { } err = grant.AppendEvent(event) case grant_es_model.UserGrantRemoved, grant_es_model.UserGrantCascadeRemoved: - return u.view.DeleteUserGrant(event.AggregateID, event.Sequence, event.CreationDate) + return u.view.DeleteUserGrant(event.AggregateID, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } if err != nil { return err } - return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate) + return u.view.PutUserGrant(grant, event) } func (u *UserGrant) processUser(event *models.Event) (err error) { @@ -119,7 +163,7 @@ func (u *UserGrant) processUser(event *models.Event) (err error) { return err } if len(grants) == 0 { - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } user, err := u.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -128,9 +172,9 @@ func (u *UserGrant) processUser(event *models.Event) (err error) { for _, grant := range grants { u.fillUserData(grant, user) } - return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate) + return u.view.PutUserGrants(grants, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } @@ -148,7 +192,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { for _, grant := range grants { u.fillProjectData(grant, project) } - return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate) + return u.view.PutUserGrants(grants, event) case proj_es_model.ProjectMemberAdded, proj_es_model.ProjectMemberChanged, proj_es_model.ProjectMemberRemoved: member := new(proj_es_model.ProjectMember) member.SetData(event) @@ -158,7 +202,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { member.SetData(event) return u.processMember(event, "PROJECT_GRANT", member.GrantID, member.UserID, member.Roles) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } @@ -169,7 +213,7 @@ func (u *UserGrant) processOrg(event *models.Event) (err error) { member.SetData(event) return u.processMember(event, "ORG", "", member.UserID, member.Roles) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } @@ -207,16 +251,16 @@ func (u *UserGrant) processIAMMember(event *models.Event, rolePrefix string, suf } grant.Sequence = event.Sequence grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate) + return u.view.PutUserGrant(grant, event) case iam_es_model.IAMMemberRemoved: member.SetData(event) grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID) if err != nil { return err } - return u.view.DeleteUserGrant(grant.ID, event.Sequence, event.CreationDate) + return u.view.DeleteUserGrant(grant.ID, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } @@ -252,7 +296,7 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st } grant.Sequence = event.Sequence grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate) + return u.view.PutUserGrant(grant, event) case org_es_model.OrgMemberRemoved, proj_es_model.ProjectMemberRemoved, proj_es_model.ProjectGrantMemberRemoved: @@ -262,18 +306,18 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st return err } if errors.IsNotFound(err) { - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } if roleSuffix != "" { roleKeys = suffixRoles(roleSuffix, roleKeys) } if grant.RoleKeys == nil { - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } grant.RoleKeys = mergeExistingRoles(rolePrefix, roleSuffix, grant.RoleKeys, nil) - return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate) + return u.view.PutUserGrant(grant, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } diff --git a/internal/auth/repository/eventsourcing/handler/user_membership.go b/internal/auth/repository/eventsourcing/handler/user_membership.go index 7b231a78b5..ddc6fa6055 100644 --- a/internal/auth/repository/eventsourcing/handler/user_membership.go +++ b/internal/auth/repository/eventsourcing/handler/user_membership.go @@ -2,6 +2,8 @@ package handler import ( "context" + + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" @@ -14,33 +16,72 @@ import ( "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" usr_model "github.com/caos/zitadel/internal/user/model" usr_es_model "github.com/caos/zitadel/internal/user/repository/view/model" ) +const ( + userMembershipTable = "auth.user_memberships" +) + type UserMembership struct { handler orgEvents *org_event.OrgEventstore projectEvents *proj_event.ProjectEventstore + subscription *eventstore.Subscription } -const ( - userMembershipTable = "auth.user_memberships" -) +func newUserMembership( + handler handler, + orgEvents *org_event.OrgEventstore, + projectEvents *proj_event.ProjectEventstore, +) *UserMembership { + h := &UserMembership{ + handler: handler, + orgEvents: orgEvents, + projectEvents: projectEvents, + } + + h.subscribe() + + return h +} + +func (m *UserMembership) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} func (m *UserMembership) ViewModel() string { return userMembershipTable } +func (_ *UserMembership) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{iam_es_model.IAMAggregate, org_es_model.OrgAggregate, proj_es_model.ProjectAggregate, model.UserAggregate} +} + +func (m *UserMembership) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := m.view.GetLatestUserMembershipSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (m *UserMembership) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestUserMembershipSequence() + sequence, err := m.view.GetLatestUserMembershipSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(iam_es_model.IAMAggregate, org_es_model.OrgAggregate, proj_es_model.ProjectAggregate, model.UserAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -74,14 +115,14 @@ func (m *UserMembership) processIam(event *models.Event) (err error) { } err = member.AppendEvent(event) case iam_es_model.IAMMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedUserMembershipSequence(event) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) + return m.view.PutUserMembership(member, event) } func (m *UserMembership) fillIamDisplayName(member *usr_es_model.UserMembershipView) { @@ -105,16 +146,16 @@ func (m *UserMembership) processOrg(event *models.Event) (err error) { } err = member.AppendEvent(event) case org_es_model.OrgMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event) case org_es_model.OrgChanged: return m.updateOrgName(event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedUserMembershipSequence(event) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) + return m.view.PutUserMembership(member, event) } func (m *UserMembership) fillOrgName(member *usr_es_model.UserMembershipView) (err error) { @@ -145,7 +186,7 @@ func (m *UserMembership) updateOrgName(event *models.Event) error { membership.DisplayName = org.Name } } - return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate) + return m.view.BulkPutUserMemberships(memberships, event) } func (m *UserMembership) processProject(event *models.Event) (err error) { @@ -168,7 +209,7 @@ func (m *UserMembership) processProject(event *models.Event) (err error) { } err = member.AppendEvent(event) case proj_es_model.ProjectMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event) case proj_es_model.ProjectGrantMemberChanged: member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant) if err != nil { @@ -176,20 +217,20 @@ func (m *UserMembership) processProject(event *models.Event) (err error) { } err = member.AppendEvent(event) case proj_es_model.ProjectGrantMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event) case proj_es_model.ProjectChanged: return m.updateProjectDisplayName(event) case proj_es_model.ProjectRemoved: - return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event) case proj_es_model.ProjectGrantRemoved: - return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedUserMembershipSequence(event) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) + return m.view.PutUserMembership(member, event) } func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) { @@ -214,15 +255,15 @@ func (m *UserMembership) updateProjectDisplayName(event *models.Event) error { for _, membership := range memberships { membership.DisplayName = project.Name } - return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate) + return m.view.BulkPutUserMemberships(memberships, event) } func (m *UserMembership) processUser(event *models.Event) (err error) { switch event.Type { case model.UserRemoved: - return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedUserMembershipSequence(event) } } diff --git a/internal/auth/repository/eventsourcing/handler/user_session.go b/internal/auth/repository/eventsourcing/handler/user_session.go index b55aacfd63..7ef182f6ae 100644 --- a/internal/auth/repository/eventsourcing/handler/user_session.go +++ b/internal/auth/repository/eventsourcing/handler/user_session.go @@ -1,34 +1,70 @@ package handler import ( + "github.com/caos/logging" req_model "github.com/caos/zitadel/internal/auth_request/model" "github.com/caos/zitadel/internal/errors" - es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" - - "github.com/caos/logging" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/user/repository/eventsourcing" user_events "github.com/caos/zitadel/internal/user/repository/eventsourcing" + es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" view_model "github.com/caos/zitadel/internal/user/repository/view/model" ) -type UserSession struct { - handler - userEvents *user_events.UserEventstore -} - const ( userSessionTable = "auth.user_sessions" ) +type UserSession struct { + handler + userEvents *user_events.UserEventstore + subscription *eventstore.Subscription +} + +func newUserSession( + handler handler, + userEvents *user_events.UserEventstore, +) *UserSession { + h := &UserSession{ + handler: handler, + userEvents: userEvents, + } + + h.subscribe() + + return h +} + +func (k *UserSession) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (u *UserSession) ViewModel() string { return userSessionTable } +func (_ *UserSession) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.UserAggregate} +} + +func (u *UserSession) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := u.view.GetLatestUserSessionSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (u *UserSession) EventQuery() (*models.SearchQuery, error) { - sequence, err := u.view.GetLatestUserSessionSequence() + sequence, err := u.view.GetLatestUserSessionSequence("") if err != nil { return nil, err } @@ -90,7 +126,7 @@ func (u *UserSession) Reduce(event *models.Event) (err error) { return err } if len(sessions) == 0 { - return u.view.ProcessedUserSessionSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserSessionSequence(event) } for _, session := range sessions { if err := session.AppendEvent(event); err != nil { @@ -100,11 +136,11 @@ func (u *UserSession) Reduce(event *models.Event) (err error) { return err } } - return u.view.PutUserSessions(sessions, event.Sequence, event.CreationDate) + return u.view.PutUserSessions(sessions, event) case es_model.UserRemoved: - return u.view.DeleteUserSessions(event.AggregateID, event.Sequence, event.CreationDate) + return u.view.DeleteUserSessions(event.AggregateID, event) default: - return u.view.ProcessedUserSessionSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserSessionSequence(event) } } @@ -124,7 +160,7 @@ func (u *UserSession) updateSession(session *view_model.UserSessionView, event * if err := u.fillUserInfo(session, event.AggregateID); err != nil { return err } - return u.view.PutUserSession(session, event.CreationDate) + return u.view.PutUserSession(session, event) } func (u *UserSession) fillUserInfo(session *view_model.UserSessionView, id string) error { diff --git a/internal/auth/repository/eventsourcing/spooler/lock.go b/internal/auth/repository/eventsourcing/spooler/lock.go index 1a7ea2990e..5fdbc5f0ae 100644 --- a/internal/auth/repository/eventsourcing/spooler/lock.go +++ b/internal/auth/repository/eventsourcing/spooler/lock.go @@ -2,18 +2,13 @@ package spooler import ( "database/sql" - es_locker "github.com/caos/zitadel/internal/eventstore/locker" "time" ) -const ( - lockTable = "auth.locks" -) - type locker struct { dbClient *sql.DB } func (l *locker) Renew(lockerID, viewModel string, waitTime time.Duration) error { - return es_locker.Renew(l.dbClient, lockTable, lockerID, viewModel, waitTime) + return nil } diff --git a/internal/auth/repository/eventsourcing/view/application.go b/internal/auth/repository/eventsourcing/view/application.go index 556d31d251..dabe7727cb 100644 --- a/internal/auth/repository/eventsourcing/view/application.go +++ b/internal/auth/repository/eventsourcing/view/application.go @@ -2,13 +2,14 @@ package view import ( "context" + "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" global_model "github.com/caos/zitadel/internal/model" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -27,28 +28,28 @@ func (v *View) SearchApplications(request *proj_model.ApplicationSearchRequest) return view.SearchApplications(v.Db, applicationTable, request) } -func (v *View) PutApplication(app *model.ApplicationView, eventTimestamp time.Time) error { +func (v *View) PutApplication(app *model.ApplicationView, event *models.Event) error { err := view.PutApplication(v.Db, applicationTable, app) if err != nil { return err } - return v.ProcessedApplicationSequence(app.Sequence, eventTimestamp) + return v.ProcessedApplicationSequence(event) } -func (v *View) PutApplications(apps []*model.ApplicationView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutApplications(apps []*model.ApplicationView, event *models.Event) error { err := view.PutApplications(v.Db, applicationTable, apps...) if err != nil { return err } - return v.ProcessedApplicationSequence(sequence, eventTimestamp) + return v.ProcessedApplicationSequence(event) } -func (v *View) DeleteApplication(appID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteApplication(appID string, event *models.Event) error { err := view.DeleteApplication(v.Db, applicationTable, appID) if err != nil { return nil } - return v.ProcessedApplicationSequence(eventSequence, eventTimestamp) + return v.ProcessedApplicationSequence(event) } func (v *View) DeleteApplicationsByProjectID(projectID string) error { @@ -56,11 +57,11 @@ func (v *View) DeleteApplicationsByProjectID(projectID string) error { } func (v *View) GetLatestApplicationSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(applicationTable) + return v.latestSequence(applicationTable, "") } -func (v *View) ProcessedApplicationSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(applicationTable, eventSequence, eventTimestamp) +func (v *View) ProcessedApplicationSequence(event *models.Event) error { + return v.saveCurrentSequence(applicationTable, event) } func (v *View) UpdateApplicationSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/external_idps.go b/internal/auth/repository/eventsourcing/view/external_idps.go index 1381611037..2928421cdc 100644 --- a/internal/auth/repository/eventsourcing/view/external_idps.go +++ b/internal/auth/repository/eventsourcing/view/external_idps.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -33,44 +33,44 @@ func (v *View) SearchExternalIDPs(request *usr_model.ExternalIDPSearchRequest) ( return view.SearchExternalIDPs(v.Db, externalIDPTable, request) } -func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, event *models.Event) error { err := view.PutExternalIDP(v.Db, externalIDPTable, externalIDP) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) PutExternalIDPs(sequence uint64, eventTimestamp time.Time, externalIDPs ...*model.ExternalIDPView) error { +func (v *View) PutExternalIDPs(event *models.Event, externalIDPs ...*model.ExternalIDPView) error { err := view.PutExternalIDPs(v.Db, externalIDPTable, externalIDPs...) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, event *models.Event) error { err := view.DeleteExternalIDP(v.Db, externalIDPTable, externalUserID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteExternalIDPsByUserID(userID string, event *models.Event) error { err := view.DeleteExternalIDPsByUserID(v.Db, externalIDPTable, userID) if err != nil { return err } - return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) GetLatestExternalIDPSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(externalIDPTable) +func (v *View) GetLatestExternalIDPSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(externalIDPTable, aggregateType) } -func (v *View) ProcessedExternalIDPSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(externalIDPTable, eventSequence, eventTimestamp) +func (v *View) ProcessedExternalIDPSequence(event *models.Event) error { + return v.saveCurrentSequence(externalIDPTable, event) } func (v *View) UpdateExternalIDPSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/idp_configs.go b/internal/auth/repository/eventsourcing/view/idp_configs.go index df591a7a00..65a932b2d1 100644 --- a/internal/auth/repository/eventsourcing/view/idp_configs.go +++ b/internal/auth/repository/eventsourcing/view/idp_configs.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/view" iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -25,28 +25,28 @@ func (v *View) SearchIDPConfigs(request *iam_model.IDPConfigSearchRequest) ([]*i return view.SearchIDPs(v.Db, idpConfigTable, request) } -func (v *View) PutIDPConfig(idp *iam_es_model.IDPConfigView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutIDPConfig(idp *iam_es_model.IDPConfigView, event *models.Event) error { err := view.PutIDP(v.Db, idpConfigTable, idp) if err != nil { return err } - return v.ProcessedIDPConfigSequence(sequence, eventTimestamp) + return v.ProcessedIDPConfigSequence(event) } -func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIDPConfig(idpID string, event *models.Event) error { err := view.DeleteIDP(v.Db, idpConfigTable, idpID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPConfigSequence(eventSequence, eventTimestamp) + return v.ProcessedIDPConfigSequence(event) } -func (v *View) GetLatestIDPConfigSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(idpConfigTable) +func (v *View) GetLatestIDPConfigSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(idpConfigTable, aggregateType) } -func (v *View) ProcessedIDPConfigSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(idpConfigTable, eventSequence, eventTimestamp) +func (v *View) ProcessedIDPConfigSequence(event *models.Event) error { + return v.saveCurrentSequence(idpConfigTable, event) } func (v *View) UpdateIDPConfigSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/idp_providers.go b/internal/auth/repository/eventsourcing/view/idp_providers.go index cf81e63745..afd25c15f8 100644 --- a/internal/auth/repository/eventsourcing/view/idp_providers.go +++ b/internal/auth/repository/eventsourcing/view/idp_providers.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -29,44 +29,44 @@ func (v *View) SearchIDPProviders(request *iam_model.IDPProviderSearchRequest) ( return view.SearchIDPProviders(v.Db, idpProviderTable, request) } -func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutIDPProvider(provider *model.IDPProviderView, event *models.Event) error { err := view.PutIDPProvider(v.Db, idpProviderTable, provider) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) PutIDPProviders(sequence uint64, eventTimestamp time.Time, providers ...*model.IDPProviderView) error { +func (v *View) PutIDPProviders(event *models.Event, providers ...*model.IDPProviderView) error { err := view.PutIDPProviders(v.Db, idpProviderTable, providers...) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, event *models.Event) error { err := view.DeleteIDPProvider(v.Db, idpProviderTable, aggregateID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) DeleteIDPProvidersByAggregateID(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIDPProvidersByAggregateID(aggregateID string, event *models.Event) error { err := view.DeleteIDPProvidersByAggregateID(v.Db, idpProviderTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) GetLatestIDPProviderSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(idpProviderTable) +func (v *View) GetLatestIDPProviderSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(idpProviderTable, aggregateType) } -func (v *View) ProcessedIDPProviderSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(idpProviderTable, eventSequence, eventTimestamp) +func (v *View) ProcessedIDPProviderSequence(event *models.Event) error { + return v.saveCurrentSequence(idpProviderTable, event) } func (v *View) UpdateIDPProviderSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/key.go b/internal/auth/repository/eventsourcing/view/key.go index c0c0f7d357..49b65cf38d 100644 --- a/internal/auth/repository/eventsourcing/view/key.go +++ b/internal/auth/repository/eventsourcing/view/key.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" key_model "github.com/caos/zitadel/internal/key/model" "github.com/caos/zitadel/internal/key/repository/view" "github.com/caos/zitadel/internal/key/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -32,36 +32,36 @@ func (v *View) GetActiveKeySet() ([]*key_model.PublicKey, error) { return key_model.PublicKeysFromKeyView(model.KeyViewsToModel(keys), v.keyAlgorithm) } -func (v *View) PutKeys(privateKey, publicKey *model.KeyView, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) PutKeys(privateKey, publicKey *model.KeyView, event *models.Event) error { err := view.PutKeys(v.Db, keyTable, privateKey, publicKey) if err != nil { return err } - return v.ProcessedKeySequence(eventSequence, eventTimestamp) + return v.ProcessedKeySequence(event) } -func (v *View) DeleteKey(keyID string, private bool, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteKey(keyID string, private bool, event *models.Event) error { err := view.DeleteKey(v.Db, keyTable, keyID, private) if err != nil { return nil } - return v.ProcessedKeySequence(eventSequence, eventTimestamp) + return v.ProcessedKeySequence(event) } -func (v *View) DeleteKeyPair(keyID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteKeyPair(keyID string, event *models.Event) error { err := view.DeleteKeyPair(v.Db, keyTable, keyID) if err != nil { return nil } - return v.ProcessedKeySequence(eventSequence, eventTimestamp) + return v.ProcessedKeySequence(event) } -func (v *View) GetLatestKeySequence() (*repository.CurrentSequence, error) { - return v.latestSequence(keyTable) +func (v *View) GetLatestKeySequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(keyTable, aggregateType) } -func (v *View) ProcessedKeySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(keyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedKeySequence(event *models.Event) error { + return v.saveCurrentSequence(keyTable, event) } func (v *View) UpdateKeySpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/login_policies.go b/internal/auth/repository/eventsourcing/view/login_policies.go index 2da8862129..2687cd8b6d 100644 --- a/internal/auth/repository/eventsourcing/view/login_policies.go +++ b/internal/auth/repository/eventsourcing/view/login_policies.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyV return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID) } -func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, event *models.Event) error { err := view.PutLoginPolicy(v.Db, loginPolicyTable, policy) if err != nil { return err } - return v.ProcessedLoginPolicySequence(sequence, eventTimestamp) + return v.ProcessedLoginPolicySequence(event) } -func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteLoginPolicy(aggregateID string, event *models.Event) error { err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedLoginPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedLoginPolicySequence(event) } -func (v *View) GetLatestLoginPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(loginPolicyTable) +func (v *View) GetLatestLoginPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(loginPolicyTable, aggregateType) } -func (v *View) ProcessedLoginPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(loginPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedLoginPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(loginPolicyTable, event) } func (v *View) UpdateLoginPolicySpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/machine_keys.go b/internal/auth/repository/eventsourcing/view/machine_keys.go index ac1a442566..4aab211292 100644 --- a/internal/auth/repository/eventsourcing/view/machine_keys.go +++ b/internal/auth/repository/eventsourcing/view/machine_keys.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -28,39 +28,39 @@ func (v *View) SearchMachineKeys(request *usr_model.MachineKeySearchRequest) ([] return view.SearchMachineKeys(v.Db, machineKeyTable, request) } -func (v *View) PutMachineKey(key *model.MachineKeyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutMachineKey(key *model.MachineKeyView, event *models.Event) error { err := view.PutMachineKey(v.Db, machineKeyTable, key) if err != nil { return err } - if sequence != 0 { - return v.ProcessedMachineKeySequence(sequence, eventTimestamp) + if event.Sequence != 0 { + return v.ProcessedMachineKeySequence(event) } return nil } -func (v *View) DeleteMachineKey(keyID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteMachineKey(keyID string, event *models.Event) error { err := view.DeleteMachineKey(v.Db, machineKeyTable, keyID) if err != nil { return nil } - return v.ProcessedMachineKeySequence(eventSequence, eventTimestamp) + return v.ProcessedMachineKeySequence(event) } -func (v *View) DeleteMachineKeysByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteMachineKeysByUserID(userID string, event *models.Event) error { err := view.DeleteMachineKey(v.Db, machineKeyTable, userID) if err != nil { return nil } - return v.ProcessedMachineKeySequence(eventSequence, eventTimestamp) + return v.ProcessedMachineKeySequence(event) } -func (v *View) GetLatestMachineKeySequence() (*repository.CurrentSequence, error) { - return v.latestSequence(machineKeyTable) +func (v *View) GetLatestMachineKeySequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(machineKeyTable, aggregateType) } -func (v *View) ProcessedMachineKeySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(machineKeyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedMachineKeySequence(event *models.Event) error { + return v.saveCurrentSequence(machineKeyTable, event) } func (v *View) UpdateMachineKeySpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/org.go b/internal/auth/repository/eventsourcing/view/org.go index 9f489f5c30..1b9a7c1b4c 100644 --- a/internal/auth/repository/eventsourcing/view/org.go +++ b/internal/auth/repository/eventsourcing/view/org.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/org/model" org_view "github.com/caos/zitadel/internal/org/repository/view" org_model "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -24,12 +24,12 @@ func (v *View) SearchOrgs(req *model.OrgSearchRequest) ([]*org_model.OrgView, ui return org_view.SearchOrgs(v.Db, orgTable, req) } -func (v *View) PutOrg(org *org_model.OrgView, eventTimestamp time.Time) error { +func (v *View) PutOrg(org *org_model.OrgView, event *models.Event) error { err := org_view.PutOrg(v.Db, orgTable, org) if err != nil { return err } - return v.ProcessedOrgSequence(org.Sequence, eventTimestamp) + return v.ProcessedOrgSequence(event) } func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) { @@ -44,10 +44,10 @@ func (v *View) UpdateOrgSpoolerRunTimestamp() error { return v.updateSpoolerRunSequence(orgTable) } -func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(orgTable) +func (v *View) GetLatestOrgSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(orgTable, aggregateType) } -func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgSequence(event *models.Event) error { + return v.saveCurrentSequence(orgTable, event) } diff --git a/internal/auth/repository/eventsourcing/view/org_iam_policy.go b/internal/auth/repository/eventsourcing/view/org_iam_policy.go index a9ee5a295f..a05592dae3 100644 --- a/internal/auth/repository/eventsourcing/view/org_iam_policy.go +++ b/internal/auth/repository/eventsourcing/view/org_iam_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) OrgIAMPolicyByAggregateID(aggregateID string) (*model.OrgIAMPolic return view.GetOrgIAMPolicyByAggregateID(v.Db, orgIAMPolicyTable, aggregateID) } -func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, event *models.Event) error { err := view.PutOrgIAMPolicy(v.Db, orgIAMPolicyTable, policy) if err != nil { return err } - return v.ProcessedOrgIAMPolicySequence(sequence, eventTimestamp) + return v.ProcessedOrgIAMPolicySequence(event) } -func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteOrgIAMPolicy(aggregateID string, event *models.Event) error { err := view.DeleteOrgIAMPolicy(v.Db, orgIAMPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedOrgIAMPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedOrgIAMPolicySequence(event) } -func (v *View) GetLatestOrgIAMPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(orgIAMPolicyTable) +func (v *View) GetLatestOrgIAMPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(orgIAMPolicyTable, aggregateType) } -func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgIAMPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(orgIAMPolicyTable, event) } func (v *View) UpdateOrgIAMPolicySpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/password_complexity_policy.go b/internal/auth/repository/eventsourcing/view/password_complexity_policy.go index 8259c89da0..43ce74f8c1 100644 --- a/internal/auth/repository/eventsourcing/view/password_complexity_policy.go +++ b/internal/auth/repository/eventsourcing/view/password_complexity_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) PasswordComplexityPolicyByAggregateID(aggregateID string) (*model return view.GetPasswordComplexityPolicyByAggregateID(v.Db, passwordComplexityPolicyTable, aggregateID) } -func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, event *models.Event) error { err := view.PutPasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordComplexityPolicySequence(sequence, eventTimestamp) + return v.ProcessedPasswordComplexityPolicySequence(event) } -func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeletePasswordComplexityPolicy(aggregateID string, event *models.Event) error { err := view.DeletePasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordComplexityPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedPasswordComplexityPolicySequence(event) } -func (v *View) GetLatestPasswordComplexityPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(passwordComplexityPolicyTable) +func (v *View) GetLatestPasswordComplexityPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(passwordComplexityPolicyTable, aggregateType) } -func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedPasswordComplexityPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(passwordComplexityPolicyTable, event) } func (v *View) UpdatePasswordComplexityPolicySpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/project_role.go b/internal/auth/repository/eventsourcing/view/project_role.go index 66c287ffa1..5c2751e154 100644 --- a/internal/auth/repository/eventsourcing/view/project_role.go +++ b/internal/auth/repository/eventsourcing/view/project_role.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -32,32 +32,32 @@ func (v *View) SearchProjectRoles(request *proj_model.ProjectRoleSearchRequest) return view.SearchProjectRoles(v.Db, projectRoleTable, request) } -func (v *View) PutProjectRole(project *model.ProjectRoleView, eventTimestamp time.Time) error { - err := view.PutProjectRole(v.Db, projectRoleTable, project) +func (v *View) PutProjectRole(role *model.ProjectRoleView, event *models.Event) error { + err := view.PutProjectRole(v.Db, projectRoleTable, role) if err != nil { return err } - return v.ProcessedProjectRoleSequence(project.Sequence, eventTimestamp) + return v.ProcessedProjectRoleSequence(event) } -func (v *View) DeleteProjectRole(projectID, orgID, key string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteProjectRole(projectID, orgID, key string, event *models.Event) error { err := view.DeleteProjectRole(v.Db, projectRoleTable, projectID, orgID, key) if err != nil { return nil } - return v.ProcessedProjectRoleSequence(eventSequence, eventTimestamp) + return v.ProcessedProjectRoleSequence(event) } func (v *View) DeleteProjectRolesByProjectID(projectID string) error { return view.DeleteProjectRolesByProjectID(v.Db, projectRoleTable, projectID) } -func (v *View) GetLatestProjectRoleSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(projectRoleTable) +func (v *View) GetLatestProjectRoleSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(projectRoleTable, aggregateType) } -func (v *View) ProcessedProjectRoleSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(projectRoleTable, eventSequence, eventTimestamp) +func (v *View) ProcessedProjectRoleSequence(event *models.Event) error { + return v.saveCurrentSequence(projectRoleTable, event) } func (v *View) UpdateProjectRoleSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/sequence.go b/internal/auth/repository/eventsourcing/view/sequence.go index 4ac2ab80cc..d9eb6c7a64 100644 --- a/internal/auth/repository/eventsourcing/view/sequence.go +++ b/internal/auth/repository/eventsourcing/view/sequence.go @@ -1,24 +1,26 @@ package view import ( - "github.com/caos/zitadel/internal/view/repository" "time" + + "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/view/repository" ) const ( sequencesTable = "auth.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimestamp time.Time) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimestamp) +func (v *View) saveCurrentSequence(viewName string, event *models.Event) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, string(event.AggregateType), event.Sequence, event.CreationDate) } -func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { - return repository.LatestSequence(v.Db, sequencesTable, viewName) +func (v *View) latestSequence(viewName, aggregateType string) (*repository.CurrentSequence, error) { + return repository.LatestSequence(v.Db, sequencesTable, viewName, aggregateType) } func (v *View) updateSpoolerRunSequence(viewName string) error { - currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName, "") if err != nil { return err } @@ -26,5 +28,8 @@ func (v *View) updateSpoolerRunSequence(viewName string) error { currentSequence.ViewName = viewName } currentSequence.LastSuccessfulSpoolerRun = time.Now() + //update all aggregate types + //TODO: not sure if all scenarios work as expected + currentSequence.AggregateType = "" return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) } diff --git a/internal/auth/repository/eventsourcing/view/token.go b/internal/auth/repository/eventsourcing/view/token.go index 4cb7c41844..67644c0865 100644 --- a/internal/auth/repository/eventsourcing/view/token.go +++ b/internal/auth/repository/eventsourcing/view/token.go @@ -1,10 +1,10 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_view "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -19,60 +19,60 @@ func (v *View) TokensByUserID(userID string) ([]*model.TokenView, error) { return usr_view.TokensByUserID(v.Db, tokenTable, userID) } -func (v *View) PutToken(token *model.TokenView, eventTimestamp time.Time) error { +func (v *View) PutToken(token *model.TokenView, event *models.Event) error { err := usr_view.PutToken(v.Db, tokenTable, token) if err != nil { return err } - return v.ProcessedTokenSequence(token.Sequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) PutTokens(token []*model.TokenView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutTokens(token []*model.TokenView, event *models.Event) error { err := usr_view.PutTokens(v.Db, tokenTable, token...) if err != nil { return err } - return v.ProcessedTokenSequence(sequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) DeleteToken(tokenID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteToken(tokenID string, event *models.Event) error { err := usr_view.DeleteToken(v.Db, tokenTable, tokenID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) DeleteSessionTokens(agentID, userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteSessionTokens(agentID, userID string, event *models.Event) error { err := usr_view.DeleteSessionTokens(v.Db, tokenTable, agentID, userID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) DeleteUserTokens(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserTokens(userID string, event *models.Event) error { err := usr_view.DeleteUserTokens(v.Db, tokenTable, userID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) DeleteApplicationTokens(eventSequence uint64, eventTimestamp time.Time, ids ...string) error { +func (v *View) DeleteApplicationTokens(event *models.Event, ids ...string) error { err := usr_view.DeleteApplicationTokens(v.Db, tokenTable, ids) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) GetLatestTokenSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(tokenTable) +func (v *View) GetLatestTokenSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(tokenTable, aggregateType) } -func (v *View) ProcessedTokenSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(tokenTable, eventSequence, eventTimestamp) +func (v *View) ProcessedTokenSequence(event *models.Event) error { + return v.saveCurrentSequence(tokenTable, event) } func (v *View) UpdateTokenSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/user.go b/internal/auth/repository/eventsourcing/view/user.go index e8b0591d22..f7eaea8505 100644 --- a/internal/auth/repository/eventsourcing/view/user.go +++ b/internal/auth/repository/eventsourcing/view/user.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -52,36 +52,36 @@ func (v *View) UserMFAs(userID string) ([]*usr_model.MultiFactor, error) { return view.UserMFAs(v.Db, userTable, userID) } -func (v *View) PutUser(user *model.UserView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUser(user *model.UserView, event *models.Event) error { err := view.PutUser(v.Db, userTable, user) if err != nil { return err } - return v.ProcessedUserSequence(sequence, eventTimestamp) + return v.ProcessedUserSequence(event) } -func (v *View) PutUsers(users []*model.UserView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUsers(users []*model.UserView, event *models.Event) error { err := view.PutUsers(v.Db, userTable, users...) if err != nil { return err } - return v.ProcessedUserSequence(sequence, eventTimestamp) + return v.ProcessedUserSequence(event) } -func (v *View) DeleteUser(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUser(userID string, event *models.Event) error { err := view.DeleteUser(v.Db, userTable, userID) if err != nil { return nil } - return v.ProcessedUserSequence(eventSequence, eventTimestamp) + return v.ProcessedUserSequence(event) } -func (v *View) GetLatestUserSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userTable) +func (v *View) GetLatestUserSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userTable, aggregateType) } -func (v *View) ProcessedUserSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserSequence(event *models.Event) error { + return v.saveCurrentSequence(userTable, event) } func (v *View) UpdateUserSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/user_grant.go b/internal/auth/repository/eventsourcing/view/user_grant.go index 230e9f5c8a..4121a210ff 100644 --- a/internal/auth/repository/eventsourcing/view/user_grant.go +++ b/internal/auth/repository/eventsourcing/view/user_grant.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" grant_model "github.com/caos/zitadel/internal/usergrant/model" "github.com/caos/zitadel/internal/usergrant/repository/view" "github.com/caos/zitadel/internal/usergrant/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -36,36 +36,36 @@ func (v *View) SearchUserGrants(request *grant_model.UserGrantSearchRequest) ([] return view.SearchUserGrants(v.Db, userGrantTable, request) } -func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUserGrant(grant *model.UserGrantView, event *models.Event) error { err := view.PutUserGrant(v.Db, userGrantTable, grant) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence, eventTimestamp) + return v.ProcessedUserGrantSequence(event) } -func (v *View) PutUserGrants(grants []*model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUserGrants(grants []*model.UserGrantView, event *models.Event) error { err := view.PutUserGrants(v.Db, userGrantTable, grants...) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence, eventTimestamp) + return v.ProcessedUserGrantSequence(event) } -func (v *View) DeleteUserGrant(grantID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserGrant(grantID string, event *models.Event) error { err := view.DeleteUserGrant(v.Db, userGrantTable, grantID) if err != nil { return nil } - return v.ProcessedUserGrantSequence(eventSequence, eventTimestamp) + return v.ProcessedUserGrantSequence(event) } -func (v *View) GetLatestUserGrantSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userGrantTable) +func (v *View) GetLatestUserGrantSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userGrantTable, aggregateType) } -func (v *View) ProcessedUserGrantSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userGrantTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserGrantSequence(event *models.Event) error { + return v.saveCurrentSequence(userGrantTable, event) } func (v *View) UpdateUserGrantSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/user_membership.go b/internal/auth/repository/eventsourcing/view/user_membership.go index 84607584ab..d13ec0ec9e 100644 --- a/internal/auth/repository/eventsourcing/view/user_membership.go +++ b/internal/auth/repository/eventsourcing/view/user_membership.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -28,60 +28,60 @@ func (v *View) SearchUserMemberships(request *usr_model.UserMembershipSearchRequ return view.SearchUserMemberships(v.Db, userMembershipTable, request) } -func (v *View) PutUserMembership(membership *model.UserMembershipView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUserMembership(membership *model.UserMembershipView, event *models.Event) error { err := view.PutUserMembership(v.Db, userMembershipTable, membership) if err != nil { return err } - return v.ProcessedUserMembershipSequence(sequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, event *models.Event) error { err := view.PutUserMemberships(v.Db, userMembershipTable, memberships...) if err != nil { return err } - return v.ProcessedUserMembershipSequence(sequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, event *models.Event) error { err := view.DeleteUserMembership(v.Db, userMembershipTable, userID, aggregateID, objectID, memberType) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) DeleteUserMembershipsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserMembershipsByUserID(userID string, event *models.Event) error { err := view.DeleteUserMembershipsByUserID(v.Db, userMembershipTable, userID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) DeleteUserMembershipsByAggregateID(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserMembershipsByAggregateID(aggregateID string, event *models.Event) error { err := view.DeleteUserMembershipsByAggregateID(v.Db, userMembershipTable, aggregateID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) DeleteUserMembershipsByAggregateIDAndObjectID(aggregateID, objectID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserMembershipsByAggregateIDAndObjectID(aggregateID, objectID string, event *models.Event) error { err := view.DeleteUserMembershipsByAggregateIDAndObjectID(v.Db, userMembershipTable, aggregateID, objectID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) GetLatestUserMembershipSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userMembershipTable) +func (v *View) GetLatestUserMembershipSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userMembershipTable, aggregateType) } -func (v *View) ProcessedUserMembershipSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userMembershipTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserMembershipSequence(event *models.Event) error { + return v.saveCurrentSequence(userMembershipTable, event) } func (v *View) UpdateUserMembershipSpoolerRunTimestamp() error { diff --git a/internal/auth/repository/eventsourcing/view/user_session.go b/internal/auth/repository/eventsourcing/view/user_session.go index 805cc04aef..f0ac1ae3cd 100644 --- a/internal/auth/repository/eventsourcing/view/user_session.go +++ b/internal/auth/repository/eventsourcing/view/user_session.go @@ -1,10 +1,10 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -27,36 +27,36 @@ func (v *View) ActiveUserSessions() ([]*model.UserSessionView, error) { return view.ActiveUserSessions(v.Db, userSessionTable) } -func (v *View) PutUserSession(userSession *model.UserSessionView, eventTimestamp time.Time) error { +func (v *View) PutUserSession(userSession *model.UserSessionView, event *models.Event) error { err := view.PutUserSession(v.Db, userSessionTable, userSession) if err != nil { return err } - return v.ProcessedUserSessionSequence(userSession.Sequence, eventTimestamp) + return v.ProcessedUserSessionSequence(event) } -func (v *View) PutUserSessions(userSession []*model.UserSessionView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUserSessions(userSession []*model.UserSessionView, event *models.Event) error { err := view.PutUserSessions(v.Db, userSessionTable, userSession...) if err != nil { return err } - return v.ProcessedUserSessionSequence(sequence, eventTimestamp) + return v.ProcessedUserSessionSequence(event) } -func (v *View) DeleteUserSessions(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserSessions(userID string, event *models.Event) error { err := view.DeleteUserSessions(v.Db, userSessionTable, userID) if err != nil { return nil } - return v.ProcessedUserSessionSequence(eventSequence, eventTimestamp) + return v.ProcessedUserSessionSequence(event) } -func (v *View) GetLatestUserSessionSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userSessionTable) +func (v *View) GetLatestUserSessionSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userSessionTable, aggregateType) } -func (v *View) ProcessedUserSessionSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userSessionTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserSessionSequence(event *models.Event) error { + return v.saveCurrentSequence(userSessionTable, event) } func (v *View) UpdateUserSessionSpoolerRunTimestamp() error { diff --git a/internal/authz/repository/eventsourcing/handler/application.go b/internal/authz/repository/eventsourcing/handler/application.go index 4b5773607e..fcb84ee675 100644 --- a/internal/authz/repository/eventsourcing/handler/application.go +++ b/internal/authz/repository/eventsourcing/handler/application.go @@ -3,27 +3,61 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/project/repository/eventsourcing" es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" view_model "github.com/caos/zitadel/internal/project/repository/view/model" ) -type Application struct { - handler -} - const ( applicationTable = "authz.applications" ) +type Application struct { + handler + subscription *eventstore.Subscription +} + +func newApplication(handler handler) *Application { + h := &Application{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (k *Application) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (a *Application) ViewModel() string { return applicationTable } +func (a *Application) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.ProjectAggregate} +} + +func (a *Application) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := a.view.GetLatestApplicationSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (a *Application) EventQuery() (*models.SearchQuery, error) { - sequence, err := a.view.GetLatestApplicationSequence() + sequence, err := a.view.GetLatestApplicationSequence("") if err != nil { return nil, err } @@ -54,14 +88,14 @@ func (a *Application) Reduce(event *models.Event) (err error) { if err != nil { return err } - return a.view.DeleteApplication(app.ID, event.Sequence, event.CreationDate) + return a.view.DeleteApplication(app.ID, event) default: - return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) + return a.view.ProcessedApplicationSequence(event) } if err != nil { return err } - return a.view.PutApplication(app, event.CreationDate) + return a.view.PutApplication(app, event) } func (a *Application) OnError(event *models.Event, spoolerError error) error { diff --git a/internal/authz/repository/eventsourcing/handler/handler.go b/internal/authz/repository/eventsourcing/handler/handler.go index 31274d77ab..2d5f816c97 100644 --- a/internal/authz/repository/eventsourcing/handler/handler.go +++ b/internal/authz/repository/eventsourcing/handler/handler.go @@ -23,29 +23,35 @@ type handler struct { bulkLimit uint64 cycleDuration time.Duration errorCountUntilSkip uint64 + + es eventstore.Eventstore +} + +func (h *handler) Eventstore() eventstore.Eventstore { + return h.es } type EventstoreRepos struct { - IamEvents *iam_events.IAMEventstore + IAMEvents *iam_events.IAMEventstore } -func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, eventstore eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults) []query.Handler { +func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults) []query.Handler { return []query.Handler{ - &UserGrant{ - handler: handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount}, - eventstore: eventstore, - iamID: systemDefaults.IamID, - iamEvents: repos.IamEvents, - }, - &Application{handler: handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount}}, - &Org{handler: handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount}}, + newUserGrant( + handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount, es}, + repos.IAMEvents, + systemDefaults.IamID), + newApplication( + handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount, es}), + newOrg( + handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}), } } func (configs Configs) cycleDuration(viewModel string) time.Duration { c, ok := configs[viewModel] if !ok { - return 1 * time.Second + return 3 * time.Minute } return c.MinimumCycleDuration.Duration } diff --git a/internal/authz/repository/eventsourcing/handler/org.go b/internal/authz/repository/eventsourcing/handler/org.go index e487831f02..34cc1a69e7 100644 --- a/internal/authz/repository/eventsourcing/handler/org.go +++ b/internal/authz/repository/eventsourcing/handler/org.go @@ -3,27 +3,62 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" + "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/org/repository/eventsourcing" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" org_model "github.com/caos/zitadel/internal/org/repository/view/model" ) -type Org struct { - handler -} - const ( orgTable = "authz.orgs" ) +type Org struct { + handler + subscription *eventstore.Subscription +} + +func newOrg(handler handler) *Org { + h := &Org{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (k *Org) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (o *Org) ViewModel() string { return orgTable } +func (_ *Org) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate} +} + +func (o *Org) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := o.view.GetLatestOrgSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (o *Org) EventQuery() (*es_models.SearchQuery, error) { - sequence, err := o.view.GetLatestOrgSequence() + sequence, err := o.view.GetLatestOrgSequence("") if err != nil { return nil, err } @@ -53,10 +88,10 @@ func (o *Org) Reduce(event *es_models.Event) error { return err } default: - return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate) + return o.view.ProcessedOrgSequence(event) } - return o.view.PutOrg(org, event.CreationDate) + return o.view.PutOrg(org, event) } func (o *Org) OnError(event *es_models.Event, spoolerErr error) error { diff --git a/internal/authz/repository/eventsourcing/handler/user_grant.go b/internal/authz/repository/eventsourcing/handler/user_grant.go index 58cd01d31c..f4a8d7c2dd 100644 --- a/internal/authz/repository/eventsourcing/handler/user_grant.go +++ b/internal/authz/repository/eventsourcing/handler/user_grant.go @@ -11,6 +11,7 @@ import ( "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "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" @@ -20,22 +21,59 @@ import ( view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model" ) -type UserGrant struct { - handler - eventstore eventstore.Eventstore - iamEvents *iam_events.IAMEventstore - iamID string - iamProjectID string -} - const ( userGrantTable = "authz.user_grants" ) +type UserGrant struct { + handler + iamEvents *iam_events.IAMEventstore + iamID string + iamProjectID string + subscription *eventstore.Subscription +} + +func newUserGrant( + handler handler, + iamEvents *iam_events.IAMEventstore, + iamID string, +) *UserGrant { + h := &UserGrant{ + handler: handler, + iamEvents: iamEvents, + iamID: iamID, + } + + h.subscribe() + + return h +} + +func (k *UserGrant) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (u *UserGrant) ViewModel() string { return userGrantTable } +func (_ *UserGrant) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{iam_es_model.IAMAggregate, org_es_model.OrgAggregate, proj_es_model.ProjectAggregate} +} + +func (u *UserGrant) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := u.view.GetLatestUserGrantSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (u *UserGrant) EventQuery() (*models.SearchQuery, error) { if u.iamProjectID == "" { err := u.setIamProjectID() @@ -43,7 +81,7 @@ func (u *UserGrant) EventQuery() (*models.SearchQuery, error) { return nil, err } } - sequence, err := u.view.GetLatestUserGrantSequence() + sequence, err := u.view.GetLatestUserGrantSequence("") if err != nil { return nil, err } @@ -75,7 +113,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { member.SetData(event) return u.processMember(event, "PROJECT_GRANT", member.GrantID, member.UserID, member.Roles) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } @@ -86,7 +124,7 @@ func (u *UserGrant) processOrg(event *models.Event) (err error) { member.SetData(event) return u.processMember(event, "ORG", "", member.UserID, member.Roles) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } @@ -124,16 +162,16 @@ func (u *UserGrant) processIAMMember(event *models.Event, rolePrefix string, suf } grant.Sequence = event.Sequence grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate) + return u.view.PutUserGrant(grant, event) case iam_es_model.IAMMemberRemoved: member.SetData(event) grant, err := u.view.UserGrantByIDs(u.iamID, u.iamProjectID, member.UserID) if err != nil { return err } - return u.view.DeleteUserGrant(grant.ID, event.Sequence, event.CreationDate) + return u.view.DeleteUserGrant(grant.ID, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } @@ -169,7 +207,7 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st } grant.Sequence = event.Sequence grant.ChangeDate = event.CreationDate - return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate) + return u.view.PutUserGrant(grant, event) case org_es_model.OrgMemberRemoved, proj_es_model.ProjectMemberRemoved, proj_es_model.ProjectGrantMemberRemoved: @@ -179,18 +217,18 @@ func (u *UserGrant) processMember(event *models.Event, rolePrefix, roleSuffix st return err } if errors.IsNotFound(err) { - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } if roleSuffix != "" { roleKeys = suffixRoles(roleSuffix, roleKeys) } if grant.RoleKeys == nil { - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } grant.RoleKeys = mergeExistingRoles(rolePrefix, roleSuffix, grant.RoleKeys, nil) - return u.view.PutUserGrant(grant, event.Sequence, event.CreationDate) + return u.view.PutUserGrant(grant, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } } diff --git a/internal/authz/repository/eventsourcing/repository.go b/internal/authz/repository/eventsourcing/repository.go index b39ad5e2e8..e42a152cdb 100644 --- a/internal/authz/repository/eventsourcing/repository.go +++ b/internal/authz/repository/eventsourcing/repository.go @@ -2,6 +2,7 @@ package eventsourcing import ( "context" + es_user "github.com/caos/zitadel/internal/user/repository/eventsourcing" "github.com/caos/zitadel/internal/api/authz" @@ -76,7 +77,7 @@ func Start(conf Config, authZ authz.Config, systemDefaults sd.SystemDefaults) (* if err != nil { return nil, err } - repos := handler.EventstoreRepos{IamEvents: iam} + repos := handler.EventstoreRepos{IAMEvents: iam} spool := spooler.StartSpooler(conf.Spooler, es, view, sqlClient, repos, systemDefaults) return &EsRepository{ diff --git a/internal/authz/repository/eventsourcing/spooler/lock.go b/internal/authz/repository/eventsourcing/spooler/lock.go index 6100f470d3..0397382276 100644 --- a/internal/authz/repository/eventsourcing/spooler/lock.go +++ b/internal/authz/repository/eventsourcing/spooler/lock.go @@ -2,7 +2,6 @@ package spooler import ( "database/sql" - es_locker "github.com/caos/zitadel/internal/eventstore/locker" "time" ) @@ -15,5 +14,5 @@ type locker struct { } func (l *locker) Renew(lockerID, viewModel string, waitTime time.Duration) error { - return es_locker.Renew(l.dbClient, lockTable, lockerID, viewModel, waitTime) + return nil } diff --git a/internal/authz/repository/eventsourcing/view/application.go b/internal/authz/repository/eventsourcing/view/application.go index a8e772b58d..07448bf64f 100644 --- a/internal/authz/repository/eventsourcing/view/application.go +++ b/internal/authz/repository/eventsourcing/view/application.go @@ -2,8 +2,8 @@ package view import ( "context" - "time" + "github.com/caos/zitadel/internal/eventstore/models" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" @@ -34,28 +34,28 @@ func (v *View) SearchApplications(request *proj_model.ApplicationSearchRequest) return view.SearchApplications(v.Db, applicationTable, request) } -func (v *View) PutApplication(project *model.ApplicationView, eventTimestamp time.Time) error { +func (v *View) PutApplication(project *model.ApplicationView, event *models.Event) error { err := view.PutApplication(v.Db, applicationTable, project) if err != nil { return err } - return v.ProcessedApplicationSequence(project.Sequence, eventTimestamp) + return v.ProcessedApplicationSequence(event) } -func (v *View) DeleteApplication(appID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteApplication(appID string, event *models.Event) error { err := view.DeleteApplication(v.Db, applicationTable, appID) if err != nil { return nil } - return v.ProcessedApplicationSequence(eventSequence, eventTimestamp) + return v.ProcessedApplicationSequence(event) } -func (v *View) GetLatestApplicationSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(applicationTable) +func (v *View) GetLatestApplicationSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(applicationTable, aggregateType) } -func (v *View) ProcessedApplicationSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(applicationTable, eventSequence, eventTimestamp) +func (v *View) ProcessedApplicationSequence(event *models.Event) error { + return v.saveCurrentSequence(applicationTable, event) } func (v *View) UpdateApplicationSpoolerRunTimestamp() error { diff --git a/internal/authz/repository/eventsourcing/view/org.go b/internal/authz/repository/eventsourcing/view/org.go index f886123b2e..6d27b5b071 100644 --- a/internal/authz/repository/eventsourcing/view/org.go +++ b/internal/authz/repository/eventsourcing/view/org.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/org/model" org_view "github.com/caos/zitadel/internal/org/repository/view" org_model "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -20,12 +20,12 @@ func (v *View) SearchOrgs(req *model.OrgSearchRequest) ([]*org_model.OrgView, ui return org_view.SearchOrgs(v.Db, orgTable, req) } -func (v *View) PutOrg(org *org_model.OrgView, eventTimestamp time.Time) error { +func (v *View) PutOrg(org *org_model.OrgView, event *models.Event) error { err := org_view.PutOrg(v.Db, orgTable, org) if err != nil { return err } - return v.ProcessedOrgSequence(org.Sequence, eventTimestamp) + return v.ProcessedOrgSequence(event) } func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) { @@ -36,12 +36,12 @@ func (v *View) ProcessedOrgFailedEvent(failedEvent *repository.FailedEvent) erro return v.saveFailedEvent(failedEvent) } -func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(orgTable) +func (v *View) GetLatestOrgSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(orgTable, aggregateType) } -func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgSequence(event *models.Event) error { + return v.saveCurrentSequence(orgTable, event) } func (v *View) UpdateOrgSpoolerRunTimestamp() error { diff --git a/internal/authz/repository/eventsourcing/view/sequence.go b/internal/authz/repository/eventsourcing/view/sequence.go index ad628fbf7b..42e6e20bfd 100644 --- a/internal/authz/repository/eventsourcing/view/sequence.go +++ b/internal/authz/repository/eventsourcing/view/sequence.go @@ -1,24 +1,26 @@ package view import ( - "github.com/caos/zitadel/internal/view/repository" "time" + + "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/view/repository" ) const ( sequencesTable = "authz.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimestamp time.Time) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimestamp) +func (v *View) saveCurrentSequence(viewName string, event *models.Event) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, string(event.AggregateType), event.Sequence, event.CreationDate) } -func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { - return repository.LatestSequence(v.Db, sequencesTable, viewName) +func (v *View) latestSequence(viewName, aggregateType string) (*repository.CurrentSequence, error) { + return repository.LatestSequence(v.Db, sequencesTable, viewName, aggregateType) } func (v *View) updateSpoolerRunSequence(viewName string) error { - currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName, "") if err != nil { return err } @@ -26,5 +28,8 @@ func (v *View) updateSpoolerRunSequence(viewName string) error { currentSequence.ViewName = viewName } currentSequence.LastSuccessfulSpoolerRun = time.Now() + //update all aggregate types + //TODO: not sure if all scenarios work as expected + currentSequence.AggregateType = "" return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) } diff --git a/internal/authz/repository/eventsourcing/view/token.go b/internal/authz/repository/eventsourcing/view/token.go index bab80f238a..da411da937 100644 --- a/internal/authz/repository/eventsourcing/view/token.go +++ b/internal/authz/repository/eventsourcing/view/token.go @@ -1,10 +1,10 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_view "github.com/caos/zitadel/internal/user/repository/view" usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -15,36 +15,36 @@ func (v *View) TokenByID(tokenID string) (*usr_view_model.TokenView, error) { return usr_view.TokenByID(v.Db, tokenTable, tokenID) } -func (v *View) PutToken(token *usr_view_model.TokenView, eventTimestamp time.Time) error { +func (v *View) PutToken(token *usr_view_model.TokenView, event *models.Event) error { err := usr_view.PutToken(v.Db, tokenTable, token) if err != nil { return err } - return v.ProcessedTokenSequence(token.Sequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) DeleteToken(tokenID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteToken(tokenID string, event *models.Event) error { err := usr_view.DeleteToken(v.Db, tokenTable, tokenID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) DeleteSessionTokens(agentID, userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteSessionTokens(agentID, userID string, event *models.Event) error { err := usr_view.DeleteSessionTokens(v.Db, tokenTable, agentID, userID) if err != nil { return nil } - return v.ProcessedTokenSequence(eventSequence, eventTimestamp) + return v.ProcessedTokenSequence(event) } -func (v *View) GetLatestTokenSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(tokenTable) +func (v *View) GetLatestTokenSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(tokenTable, aggregateType) } -func (v *View) ProcessedTokenSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(tokenTable, eventSequence, eventTimestamp) +func (v *View) ProcessedTokenSequence(event *models.Event) error { + return v.saveCurrentSequence(tokenTable, event) } func (v *View) UpdateTokenSpoolerRunTimestamp() error { diff --git a/internal/authz/repository/eventsourcing/view/user_grant.go b/internal/authz/repository/eventsourcing/view/user_grant.go index 68154dc3c9..119ab9ae23 100644 --- a/internal/authz/repository/eventsourcing/view/user_grant.go +++ b/internal/authz/repository/eventsourcing/view/user_grant.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" grant_model "github.com/caos/zitadel/internal/usergrant/model" "github.com/caos/zitadel/internal/usergrant/repository/view" "github.com/caos/zitadel/internal/usergrant/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -32,28 +32,28 @@ func (v *View) SearchUserGrants(request *grant_model.UserGrantSearchRequest) ([] return view.SearchUserGrants(v.Db, userGrantTable, request) } -func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUserGrant(grant *model.UserGrantView, event *models.Event) error { err := view.PutUserGrant(v.Db, userGrantTable, grant) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence, eventTimestamp) + return v.ProcessedUserGrantSequence(event) } -func (v *View) DeleteUserGrant(grantID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserGrant(grantID string, event *models.Event) error { err := view.DeleteUserGrant(v.Db, userGrantTable, grantID) if err != nil { return nil } - return v.ProcessedUserGrantSequence(eventSequence, eventTimestamp) + return v.ProcessedUserGrantSequence(event) } -func (v *View) GetLatestUserGrantSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userGrantTable) +func (v *View) GetLatestUserGrantSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userGrantTable, aggregateType) } -func (v *View) ProcessedUserGrantSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userGrantTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserGrantSequence(event *models.Event) error { + return v.saveCurrentSequence(userGrantTable, event) } func (v *View) UpdateUserGrantSpoolerRunTimestamp() error { diff --git a/internal/eventstore/eventstore.go b/internal/eventstore/eventstore.go index 138599b856..b4c0e5a745 100644 --- a/internal/eventstore/eventstore.go +++ b/internal/eventstore/eventstore.go @@ -14,6 +14,7 @@ type Eventstore interface { PushAggregates(ctx context.Context, aggregates ...*models.Aggregate) error FilterEvents(ctx context.Context, searchQuery *models.SearchQuery) (events []*models.Event, err error) LatestSequence(ctx context.Context, searchQuery *models.SearchQueryFactory) (uint64, error) + Subscribe(aggregates ...models.AggregateType) *Subscription } var _ Eventstore = (*eventstore)(nil) @@ -42,6 +43,8 @@ func (es *eventstore) PushAggregates(ctx context.Context, aggregates ...*models. if err != nil { return err } + + go notify(aggregates) return nil } diff --git a/internal/eventstore/mock/eventstore.mock.go b/internal/eventstore/mock/eventstore.mock.go index 18fb7a949a..fbe1990856 100644 --- a/internal/eventstore/mock/eventstore.mock.go +++ b/internal/eventstore/mock/eventstore.mock.go @@ -6,6 +6,7 @@ package mock import ( context "context" + eventstore "github.com/caos/zitadel/internal/eventstore" models "github.com/caos/zitadel/internal/eventstore/models" gomock "github.com/golang/mock/gomock" reflect "reflect" @@ -110,3 +111,21 @@ func (mr *MockEventstoreMockRecorder) PushAggregates(arg0 interface{}, arg1 ...i varargs := append([]interface{}{arg0}, arg1...) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PushAggregates", reflect.TypeOf((*MockEventstore)(nil).PushAggregates), varargs...) } + +// Subscribe mocks base method +func (m *MockEventstore) Subscribe(arg0 ...models.AggregateType) *eventstore.Subscription { + m.ctrl.T.Helper() + varargs := []interface{}{} + for _, a := range arg0 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Subscribe", varargs...) + ret0, _ := ret[0].(*eventstore.Subscription) + return ret0 +} + +// Subscribe indicates an expected call of Subscribe +func (mr *MockEventstoreMockRecorder) Subscribe(arg0 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subscribe", reflect.TypeOf((*MockEventstore)(nil).Subscribe), arg0...) +} diff --git a/internal/eventstore/models/aggregate.go b/internal/eventstore/models/aggregate.go index 66026b05d5..a0a5c88779 100644 --- a/internal/eventstore/models/aggregate.go +++ b/internal/eventstore/models/aggregate.go @@ -27,6 +27,10 @@ type Aggregate struct { Precondition *precondition } +func (a *Aggregate) Type() AggregateType { + return a.typ +} + type precondition struct { Query *SearchQuery Validation func(...*Event) error diff --git a/internal/eventstore/models/search_query.go b/internal/eventstore/models/search_query.go index 3530db46a8..06cbf97f1d 100644 --- a/internal/eventstore/models/search_query.go +++ b/internal/eventstore/models/search_query.go @@ -11,7 +11,8 @@ type SearchQueryFactory struct { desc bool aggregateTypes []AggregateType aggregateIDs []string - eventSequence uint64 + sequenceFrom uint64 + sequenceTo uint64 eventTypes []EventType resourceOwner string } @@ -51,7 +52,11 @@ func FactoryFromSearchQuery(query *SearchQuery) *SearchQueryFactory { factory = factory.AggregateIDs(aggregateIDs...) } case Field_LatestSequence: - factory = factory.SequenceGreater(filter.value.(uint64)) + if filter.operation == Operation_Greater { + factory = factory.SequenceGreater(filter.value.(uint64)) + } else { + factory = factory.SequenceLess(filter.value.(uint64)) + } case Field_ResourceOwner: factory = factory.ResourceOwner(filter.value.(string)) case Field_EventType: @@ -82,7 +87,12 @@ func (factory *SearchQueryFactory) Limit(limit uint64) *SearchQueryFactory { } func (factory *SearchQueryFactory) SequenceGreater(sequence uint64) *SearchQueryFactory { - factory.eventSequence = sequence + factory.sequenceFrom = sequence + return factory +} + +func (factory *SearchQueryFactory) SequenceLess(sequence uint64) *SearchQueryFactory { + factory.sequenceTo = sequence return factory } @@ -128,7 +138,8 @@ func (factory *SearchQueryFactory) Build() (*searchQuery, error) { for _, f := range []func() *Filter{ factory.aggregateIDFilter, - factory.eventSequenceFilter, + factory.sequenceFromFilter, + factory.sequenceToFilter, factory.eventTypeFilter, factory.resourceOwnerFilter, } { @@ -172,15 +183,26 @@ func (factory *SearchQueryFactory) aggregateTypeFilter() *Filter { return NewFilter(Field_AggregateType, factory.aggregateTypes, Operation_In) } -func (factory *SearchQueryFactory) eventSequenceFilter() *Filter { - if factory.eventSequence == 0 { +func (factory *SearchQueryFactory) sequenceFromFilter() *Filter { + if factory.sequenceFrom == 0 { return nil } sortOrder := Operation_Greater if factory.desc { sortOrder = Operation_Less } - return NewFilter(Field_LatestSequence, factory.eventSequence, sortOrder) + return NewFilter(Field_LatestSequence, factory.sequenceFrom, sortOrder) +} + +func (factory *SearchQueryFactory) sequenceToFilter() *Filter { + if factory.sequenceTo == 0 { + return nil + } + sortOrder := Operation_Less + if factory.desc { + sortOrder = Operation_Greater + } + return NewFilter(Field_LatestSequence, factory.sequenceTo, sortOrder) } func (factory *SearchQueryFactory) resourceOwnerFilter() *Filter { diff --git a/internal/eventstore/models/search_query_old.go b/internal/eventstore/models/search_query_old.go index c803fac64b..0d6e1ebc6c 100644 --- a/internal/eventstore/models/search_query_old.go +++ b/internal/eventstore/models/search_query_old.go @@ -58,6 +58,12 @@ func (q *SearchQuery) LatestSequenceFilter(sequence uint64) *SearchQuery { return q.setFilter(NewFilter(Field_LatestSequence, sequence, sortOrder)) } +func (q *SearchQuery) SequenceBetween(from, to uint64) *SearchQuery { + q.setFilter(NewFilter(Field_LatestSequence, from, Operation_Greater)) + q.setFilter(NewFilter(Field_LatestSequence, to, Operation_Less)) + return q +} + func (q *SearchQuery) ResourceOwnerFilter(resourceOwner string) *SearchQuery { return q.setFilter(NewFilter(Field_ResourceOwner, resourceOwner, Operation_Equals)) } diff --git a/internal/eventstore/models/search_query_test.go b/internal/eventstore/models/search_query_test.go index ac9380b4d9..b52f6490cf 100644 --- a/internal/eventstore/models/search_query_test.go +++ b/internal/eventstore/models/search_query_test.go @@ -103,7 +103,7 @@ func TestSearchQueryFactorySetters(t *testing.T) { setters: []func(*SearchQueryFactory) *SearchQueryFactory{testSetSequence(90)}, }, res: &SearchQueryFactory{ - eventSequence: 90, + sequenceFrom: 90, }, }, { diff --git a/internal/eventstore/query/handler.go b/internal/eventstore/query/handler.go index 36bba2547e..07f4f6ce3d 100755 --- a/internal/eventstore/query/handler.go +++ b/internal/eventstore/query/handler.go @@ -1,8 +1,11 @@ package query import ( + "context" "time" + "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" ) @@ -14,4 +17,42 @@ type Handler interface { OnSuccess() error MinimumCycleDuration() time.Duration QueryLimit() uint64 + + AggregateTypes() []models.AggregateType + CurrentSequence(*models.Event) (uint64, error) + Eventstore() eventstore.Eventstore +} + +func ReduceEvent(handler Handler, event *models.Event) { + currentSequence, err := handler.CurrentSequence(event) + if err != nil { + logging.Log("HANDL-BmpkC").WithError(err).Warn("unable to get current sequence") + return + } + if event.PreviousSequence > currentSequence { + searchQuery := models.NewSearchQuery(). + AggregateTypeFilter(handler.AggregateTypes()...). + SequenceBetween(currentSequence, event.PreviousSequence) + + events, err := handler.Eventstore().FilterEvents(context.Background(), searchQuery) + if err != nil { + logging.LogWithFields("HANDL-L6YH1", "seq", event.Sequence).Warn("filter failed") + return + } + for _, previousEvent := range events { + //if other process already updated view + //TODO: correct? + if event.PreviousSequence > previousEvent.Sequence { + continue + } + err = handler.Reduce(previousEvent) + logging.LogWithFields("HANDL-V42TI", "seq", previousEvent.Sequence).OnError(err).Warn("reduce failed") + return + } + } else if event.PreviousSequence > 0 && event.PreviousSequence < currentSequence { + logging.LogWithFields("HANDL-w9Bdy", "previousSeq", event.PreviousSequence, "currentSeq", currentSequence).Debug("already processed") + return + } + err = handler.Reduce(event) + logging.LogWithFields("HANDL-wQDL2", "seq", event.Sequence).OnError(err).Warn("reduce failed") } diff --git a/internal/eventstore/spooler/spooler.go b/internal/eventstore/spooler/spooler.go index fb480f7916..723fbe9229 100644 --- a/internal/eventstore/spooler/spooler.go +++ b/internal/eventstore/spooler/spooler.go @@ -167,7 +167,7 @@ func (s *spooledHandler) lock(ctx context.Context, errs chan<- error, workerID s func HandleError(event *models.Event, failedErr error, latestFailedEvent func(sequence uint64) (*repository.FailedEvent, error), processFailedEvent func(*repository.FailedEvent) error, - processSequence func(uint64, time.Time) error, errorCountUntilSkip uint64) error { + processSequence func(*models.Event) error, errorCountUntilSkip uint64) error { failedEvent, err := latestFailedEvent(event.Sequence) if err != nil { return err @@ -179,7 +179,7 @@ func HandleError(event *models.Event, failedErr error, return err } if errorCountUntilSkip <= failedEvent.FailureCount { - return processSequence(event.Sequence, event.CreationDate) + return processSequence(event) } return nil } diff --git a/internal/eventstore/spooler/spooler_test.go b/internal/eventstore/spooler/spooler_test.go index 721ad74e26..13c6737aa0 100644 --- a/internal/eventstore/spooler/spooler_test.go +++ b/internal/eventstore/spooler/spooler_test.go @@ -24,6 +24,18 @@ type testHandler struct { bulkLimit uint64 } +func (h *testHandler) AggregateTypes() []models.AggregateType { + return nil +} + +func (h *testHandler) CurrentSequence(event *models.Event) (uint64, error) { + return 0, nil +} + +func (h *testHandler) Eventstore() eventstore.Eventstore { + return nil +} + func (h *testHandler) ViewModel() string { return h.viewModel } @@ -55,6 +67,8 @@ type eventstoreStub struct { err error } +func (es *eventstoreStub) Subscribe(...models.AggregateType) *eventstore.Subscription { return nil } + func (es *eventstoreStub) Health(ctx context.Context) error { return nil } @@ -432,7 +446,7 @@ func TestHandleError(t *testing.T) { func(*repository.FailedEvent) error { return nil }, - func(uint64, time.Time) error { + func(*models.Event) error { processedSequence = true return nil }, diff --git a/internal/eventstore/subscription.go b/internal/eventstore/subscription.go new file mode 100644 index 0000000000..37aa0dd45c --- /dev/null +++ b/internal/eventstore/subscription.go @@ -0,0 +1,73 @@ +package eventstore + +import ( + "sync" + + "github.com/caos/zitadel/internal/eventstore/models" +) + +var ( + subscriptions map[models.AggregateType][]*Subscription = map[models.AggregateType][]*Subscription{} + subsMutext sync.Mutex +) + +type Subscription struct { + Events chan *models.Event + aggregates []models.AggregateType +} + +func (es *eventstore) Subscribe(aggregates ...models.AggregateType) *Subscription { + events := make(chan *models.Event, 100) + sub := &Subscription{ + Events: events, + aggregates: aggregates, + } + + subsMutext.Lock() + defer subsMutext.Unlock() + + for _, aggregate := range aggregates { + _, ok := subscriptions[aggregate] + if !ok { + subscriptions[aggregate] = make([]*Subscription, 0, 1) + } + subscriptions[aggregate] = append(subscriptions[aggregate], sub) + } + + return sub +} + +func notify(aggregates []*models.Aggregate) { + subsMutext.Lock() + defer subsMutext.Unlock() + for _, aggregate := range aggregates { + subs, ok := subscriptions[aggregate.Type()] + if !ok { + continue + } + for _, sub := range subs { + for _, event := range aggregate.Events { + sub.Events <- event + } + } + } +} + +func (s *Subscription) Unsubscribe() { + subsMutext.Lock() + defer subsMutext.Unlock() + for _, aggregate := range s.aggregates { + subs, ok := subscriptions[aggregate] + if !ok { + continue + } + for i := len(subs) - 1; i >= 0; i-- { + if subs[i] == s { + subs[i] = subs[len(subs)-1] + subs[len(subs)-1] = nil + subs = subs[:len(subs)-1] + } + } + } + close(s.Events) +} diff --git a/internal/iam/repository/eventsourcing/model/login_policy.go b/internal/iam/repository/eventsourcing/model/login_policy.go index 7b28b18b96..2dbfea499a 100644 --- a/internal/iam/repository/eventsourcing/model/login_policy.go +++ b/internal/iam/repository/eventsourcing/model/login_policy.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" diff --git a/internal/iam/repository/eventsourcing/model/org_iam_policy.go b/internal/iam/repository/eventsourcing/model/org_iam_policy.go index 3056750803..1612d84c12 100644 --- a/internal/iam/repository/eventsourcing/model/org_iam_policy.go +++ b/internal/iam/repository/eventsourcing/model/org_iam_policy.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" diff --git a/internal/iam/repository/eventsourcing/model/password_age_policy.go b/internal/iam/repository/eventsourcing/model/password_age_policy.go index 86c65247d9..7d4b96d4d4 100644 --- a/internal/iam/repository/eventsourcing/model/password_age_policy.go +++ b/internal/iam/repository/eventsourcing/model/password_age_policy.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" diff --git a/internal/iam/repository/eventsourcing/model/password_complexity_policy.go b/internal/iam/repository/eventsourcing/model/password_complexity_policy.go index 37dc2db784..148db9f422 100644 --- a/internal/iam/repository/eventsourcing/model/password_complexity_policy.go +++ b/internal/iam/repository/eventsourcing/model/password_complexity_policy.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" diff --git a/internal/iam/repository/eventsourcing/model/password_lockout_policy.go b/internal/iam/repository/eventsourcing/model/password_lockout_policy.go index e4878c82f9..15c78c45ac 100644 --- a/internal/iam/repository/eventsourcing/model/password_lockout_policy.go +++ b/internal/iam/repository/eventsourcing/model/password_lockout_policy.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" diff --git a/internal/management/repository/eventsourcing/eventstore/org.go b/internal/management/repository/eventsourcing/eventstore/org.go index 6bc11af854..74c37908b7 100644 --- a/internal/management/repository/eventsourcing/eventstore/org.go +++ b/internal/management/repository/eventsourcing/eventstore/org.go @@ -108,7 +108,7 @@ func (repo *OrgRepository) GetMyOrgIamPolicy(ctx context.Context) (*iam_model.Or func (repo *OrgRepository) SearchMyOrgDomains(ctx context.Context, request *org_model.OrgDomainSearchRequest) (*org_model.OrgDomainSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) request.Queries = append(request.Queries, &org_model.OrgDomainSearchQuery{Key: org_model.OrgDomainSearchKeyOrgID, Method: global_model.SearchMethodEquals, Value: authz.GetCtxData(ctx).OrgID}) - sequence, sequenceErr := repo.View.GetLatestOrgDomainSequence() + sequence, sequenceErr := repo.View.GetLatestOrgDomainSequence("") logging.Log("EVENT-SLowp").OnError(sequenceErr).WithField("traceID", tracing.TraceIDFromCtx(ctx)).Warn("could not read latest org domain sequence") domains, count, err := repo.View.SearchOrgDomains(request) if err != nil { @@ -205,7 +205,7 @@ func (repo *OrgRepository) RemoveMyOrgMember(ctx context.Context, userID string) func (repo *OrgRepository) SearchMyOrgMembers(ctx context.Context, request *org_model.OrgMemberSearchRequest) (*org_model.OrgMemberSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) request.Queries[len(request.Queries)-1] = &org_model.OrgMemberSearchQuery{Key: org_model.OrgMemberSearchKeyOrgID, Method: global_model.SearchMethodEquals, Value: authz.GetCtxData(ctx).OrgID} - sequence, sequenceErr := repo.View.GetLatestOrgMemberSequence() + sequence, sequenceErr := repo.View.GetLatestOrgMemberSequence("") logging.Log("EVENT-Smu3d").OnError(sequenceErr).Warn("could not read latest org member sequence") members, count, err := repo.View.SearchOrgMembers(request) if err != nil { @@ -292,7 +292,7 @@ func (repo *OrgRepository) SearchIDPConfigs(ctx context.Context, request *iam_mo request.EnsureLimit(repo.SearchLimit) request.AppendMyOrgQuery(authz.GetCtxData(ctx).OrgID, repo.SystemDefaults.IamID) - sequence, sequenceErr := repo.View.GetLatestIDPConfigSequence() + sequence, sequenceErr := repo.View.GetLatestIDPConfigSequence("") logging.Log("EVENT-Dk8si").OnError(sequenceErr).Warn("could not read latest idp config sequence") idps, count, err := repo.View.SearchIDPConfigs(request) if err != nil { @@ -414,7 +414,7 @@ func (repo *OrgRepository) SearchIDPProviders(ctx context.Context, request *iam_ request.AppendAggregateIDQuery(authz.GetCtxData(ctx).OrgID) } request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestIDPProviderSequence() + sequence, sequenceErr := repo.View.GetLatestIDPProviderSequence("") logging.Log("EVENT-Tuiks").OnError(sequenceErr).Warn("could not read latest iam sequence") providers, count, err := repo.View.SearchIDPProviders(request) if err != nil { diff --git a/internal/management/repository/eventsourcing/eventstore/project.go b/internal/management/repository/eventsourcing/eventstore/project.go index 5a9343ff11..2d949a3f95 100644 --- a/internal/management/repository/eventsourcing/eventstore/project.go +++ b/internal/management/repository/eventsourcing/eventstore/project.go @@ -118,7 +118,7 @@ func (repo *ProjectRepo) RemoveProject(ctx context.Context, projectID string) er func (repo *ProjectRepo) SearchProjects(ctx context.Context, request *proj_model.ProjectViewSearchRequest) (*proj_model.ProjectViewSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestProjectSequence() + sequence, sequenceErr := repo.View.GetLatestProjectSequence("") logging.Log("EVENT-Edc56").OnError(sequenceErr).Warn("could not read latest project sequence") permissions := authz.GetRequestPermissionsFromCtx(ctx) @@ -198,7 +198,7 @@ func (repo *ProjectRepo) RemoveProjectMember(ctx context.Context, projectID, use func (repo *ProjectRepo) SearchProjectMembers(ctx context.Context, request *proj_model.ProjectMemberSearchRequest) (*proj_model.ProjectMemberSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestProjectMemberSequence() + sequence, sequenceErr := repo.View.GetLatestProjectMemberSequence("") logging.Log("EVENT-3dgt6").OnError(sequenceErr).Warn("could not read latest project member sequence") members, count, err := repo.View.SearchProjectMembers(request) if err != nil { @@ -270,7 +270,7 @@ func (repo *ProjectRepo) RemoveProjectRole(ctx context.Context, projectID, key s func (repo *ProjectRepo) SearchProjectRoles(ctx context.Context, projectID string, request *proj_model.ProjectRoleSearchRequest) (*proj_model.ProjectRoleSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) request.AppendProjectQuery(projectID) - sequence, sequenceErr := repo.View.GetLatestProjectRoleSequence() + sequence, sequenceErr := repo.View.GetLatestProjectRoleSequence("") logging.Log("LSp0d-47suf").OnError(sequenceErr).Warn("could not read latest project role sequence") roles, count, err := repo.View.SearchProjectRoles(request) if err != nil { @@ -366,7 +366,7 @@ func (repo *ProjectRepo) RemoveApplication(ctx context.Context, projectID, appID func (repo *ProjectRepo) SearchApplications(ctx context.Context, request *proj_model.ApplicationSearchRequest) (*proj_model.ApplicationSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestApplicationSequence() + sequence, sequenceErr := repo.View.GetLatestApplicationSequence("") logging.Log("EVENT-SKe8s").OnError(sequenceErr).Warn("could not read latest application sequence") apps, count, err := repo.View.SearchApplications(request) if err != nil { @@ -423,7 +423,7 @@ func (repo *ProjectRepo) ProjectGrantByID(ctx context.Context, grantID string) ( func (repo *ProjectRepo) SearchProjectGrants(ctx context.Context, request *proj_model.ProjectGrantViewSearchRequest) (*proj_model.ProjectGrantViewSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestProjectGrantSequence() + sequence, sequenceErr := repo.View.GetLatestProjectGrantSequence("") logging.Log("EVENT-Skw9f").OnError(sequenceErr).Warn("could not read latest project grant sequence") projects, count, err := repo.View.SearchProjectGrants(request) if err != nil { @@ -444,7 +444,7 @@ func (repo *ProjectRepo) SearchProjectGrants(ctx context.Context, request *proj_ func (repo *ProjectRepo) SearchGrantedProjects(ctx context.Context, request *proj_model.ProjectGrantViewSearchRequest) (*proj_model.ProjectGrantViewSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestProjectGrantSequence() + sequence, sequenceErr := repo.View.GetLatestProjectGrantSequence("") logging.Log("EVENT-Skw9f").OnError(sequenceErr).Warn("could not read latest project grant sequence") permissions := authz.GetRequestPermissionsFromCtx(ctx) @@ -612,7 +612,7 @@ func (repo *ProjectRepo) RemoveProjectGrantMember(ctx context.Context, projectID func (repo *ProjectRepo) SearchProjectGrantMembers(ctx context.Context, request *proj_model.ProjectGrantMemberSearchRequest) (*proj_model.ProjectGrantMemberSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestProjectGrantMemberSequence() + sequence, sequenceErr := repo.View.GetLatestProjectGrantMemberSequence("") logging.Log("EVENT-Du8sk").OnError(sequenceErr).Warn("could not read latest project grant sequence") members, count, err := repo.View.SearchProjectGrantMembers(request) if err != nil { diff --git a/internal/management/repository/eventsourcing/eventstore/user.go b/internal/management/repository/eventsourcing/eventstore/user.go index 3d718e2f24..f1b6e62ef7 100644 --- a/internal/management/repository/eventsourcing/eventstore/user.go +++ b/internal/management/repository/eventsourcing/eventstore/user.go @@ -158,7 +158,7 @@ func (repo *UserRepo) RemoveUser(ctx context.Context, id string) error { func (repo *UserRepo) SearchUsers(ctx context.Context, request *usr_model.UserSearchRequest) (*usr_model.UserSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestUserSequence() + sequence, sequenceErr := repo.View.GetLatestUserSequence("") logging.Log("EVENT-Lcn7d").OnError(sequenceErr).Warn("could not read latest user sequence") users, count, err := repo.View.SearchUsers(request) if err != nil { @@ -276,7 +276,7 @@ func (repo *UserRepo) ProfileByID(ctx context.Context, userID string) (*usr_mode func (repo *UserRepo) SearchExternalIDPs(ctx context.Context, request *usr_model.ExternalIDPSearchRequest) (*usr_model.ExternalIDPSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, seqErr := repo.View.GetLatestExternalIDPSequence() + sequence, seqErr := repo.View.GetLatestExternalIDPSequence("") logging.Log("EVENT-Qs7uf").OnError(seqErr).Warn("could not read latest external idp sequence") externalIDPS, count, err := repo.View.SearchExternalIDPs(request) if err != nil { @@ -313,7 +313,7 @@ func (repo *UserRepo) GetMachineKey(ctx context.Context, userID, keyID string) ( func (repo *UserRepo) SearchMachineKeys(ctx context.Context, request *usr_model.MachineKeySearchRequest) (*usr_model.MachineKeySearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, seqErr := repo.View.GetLatestMachineKeySequence() + sequence, seqErr := repo.View.GetLatestMachineKeySequence("") logging.Log("EVENT-Sk8fs").OnError(seqErr).Warn("could not read latest user sequence") keys, count, err := repo.View.SearchMachineKeys(request) if err != nil { @@ -415,7 +415,7 @@ func (repo *UserRepo) ChangeAddress(ctx context.Context, address *usr_model.Addr func (repo *UserRepo) SearchUserMemberships(ctx context.Context, request *usr_model.UserMembershipSearchRequest) (*usr_model.UserMembershipSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestUserMembershipSequence() + sequence, sequenceErr := repo.View.GetLatestUserMembershipSequence("") logging.Log("EVENT-Dn7sf").OnError(sequenceErr).Warn("could not read latest user sequence") result := handleSearchUserMembershipsPermissions(ctx, request, sequence) diff --git a/internal/management/repository/eventsourcing/eventstore/user_grant.go b/internal/management/repository/eventsourcing/eventstore/user_grant.go index 09568b64fc..d2f4f337e9 100644 --- a/internal/management/repository/eventsourcing/eventstore/user_grant.go +++ b/internal/management/repository/eventsourcing/eventstore/user_grant.go @@ -116,7 +116,7 @@ func (repo *UserGrantRepo) BulkRemoveUserGrant(ctx context.Context, grantIDs ... func (repo *UserGrantRepo) SearchUserGrants(ctx context.Context, request *grant_model.UserGrantSearchRequest) (*grant_model.UserGrantSearchResponse, error) { request.EnsureLimit(repo.SearchLimit) - sequence, sequenceErr := repo.View.GetLatestUserGrantSequence() + sequence, sequenceErr := repo.View.GetLatestUserGrantSequence("") logging.Log("EVENT-5Viwf").OnError(sequenceErr).Warn("could not read latest user grant sequence") result := handleSearchUserGrantPermissions(ctx, request, sequence) diff --git a/internal/management/repository/eventsourcing/handler/application.go b/internal/management/repository/eventsourcing/handler/application.go index 8d1490c433..442eae59b3 100644 --- a/internal/management/repository/eventsourcing/handler/application.go +++ b/internal/management/repository/eventsourcing/handler/application.go @@ -5,7 +5,9 @@ import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/project/repository/eventsourcing" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" @@ -13,21 +15,57 @@ import ( view_model "github.com/caos/zitadel/internal/project/repository/view/model" ) -type Application struct { - handler - projectEvents *proj_event.ProjectEventstore -} - const ( applicationTable = "management.applications" ) +type Application struct { + handler + projectEvents *proj_event.ProjectEventstore + subscription *eventstore.Subscription +} + +func newApplication( + handler handler, + projectEvents *proj_event.ProjectEventstore, +) *Application { + h := &Application{ + handler: handler, + projectEvents: projectEvents, + } + + h.subscribe() + + return h +} + +func (a *Application) subscribe() { + a.subscription = a.es.Subscribe(a.AggregateTypes()...) + go func() { + for event := range a.subscription.Events { + query.ReduceEvent(a, event) + } + }() +} + func (a *Application) ViewModel() string { return applicationTable } +func (_ *Application) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.ProjectAggregate} +} + +func (a *Application) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := a.view.GetLatestApplicationSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (a *Application) EventQuery() (*models.SearchQuery, error) { - sequence, err := a.view.GetLatestApplicationSequence() + sequence, err := a.view.GetLatestApplicationSequence("") if err != nil { return nil, err } @@ -65,30 +103,30 @@ func (a *Application) Reduce(event *models.Event) (err error) { if err != nil { return err } - return a.view.DeleteApplication(app.ID, event.Sequence, event.CreationDate) + return a.view.DeleteApplication(app.ID, event) case es_model.ProjectChanged: apps, err := a.view.ApplicationsByProjectID(event.AggregateID) if err != nil { return err } if len(apps) == 0 { - return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) + return a.view.ProcessedApplicationSequence(event) } for _, app := range apps { if err := app.AppendEvent(event); err != nil { return err } } - return a.view.PutApplications(apps, event.Sequence, event.CreationDate) + return a.view.PutApplications(apps, event) case es_model.ProjectRemoved: return a.view.DeleteApplicationsByProjectID(event.AggregateID) default: - return a.view.ProcessedApplicationSequence(event.Sequence, event.CreationDate) + return a.view.ProcessedApplicationSequence(event) } if err != nil { return err } - return a.view.PutApplication(app, event.CreationDate) + return a.view.PutApplication(app, event) } func (a *Application) OnError(event *models.Event, spoolerError error) error { diff --git a/internal/management/repository/eventsourcing/handler/handler.go b/internal/management/repository/eventsourcing/handler/handler.go index 531a9db468..56ea997f2f 100644 --- a/internal/management/repository/eventsourcing/handler/handler.go +++ b/internal/management/repository/eventsourcing/handler/handler.go @@ -25,6 +25,12 @@ type handler struct { bulkLimit uint64 cycleDuration time.Duration errorCountUntilSkip uint64 + + es eventstore.Eventstore +} + +func (h *handler) Eventstore() eventstore.Eventstore { + return h.es } type EventstoreRepos struct { @@ -34,49 +40,76 @@ type EventstoreRepos struct { IamEvents *iam_event.IAMEventstore } -func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, eventstore eventstore.Eventstore, repos EventstoreRepos, defaults systemdefaults.SystemDefaults) []query.Handler { +func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, defaults systemdefaults.SystemDefaults) []query.Handler { return []query.Handler{ - &Project{handler: handler{view, bulkLimit, configs.cycleDuration("Project"), errorCount}, - eventstore: eventstore}, - &ProjectGrant{handler: handler{view, bulkLimit, configs.cycleDuration("ProjectGrant"), errorCount}, - eventstore: eventstore, projectEvents: repos.ProjectEvents, orgEvents: repos.OrgEvents}, - &ProjectRole{handler: handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount}, - projectEvents: repos.ProjectEvents}, - &ProjectMember{handler: handler{view, bulkLimit, configs.cycleDuration("ProjectMember"), errorCount}, - userEvents: repos.UserEvents}, - &ProjectGrantMember{handler: handler{view, bulkLimit, configs.cycleDuration("ProjectGrantMember"), errorCount}, - userEvents: repos.UserEvents}, - &Application{handler: handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount}, - projectEvents: repos.ProjectEvents}, - &User{handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, - eventstore: eventstore, orgEvents: repos.OrgEvents, iamEvents: repos.IamEvents, iamID: defaults.IamID}, - &UserGrant{handler: handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount}, - projectEvents: repos.ProjectEvents, userEvents: repos.UserEvents, orgEvents: repos.OrgEvents}, - &Org{handler: handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount}}, - &OrgMember{handler: handler{view, bulkLimit, configs.cycleDuration("OrgMember"), errorCount}, - userEvents: repos.UserEvents}, - &OrgDomain{handler: handler{view, bulkLimit, configs.cycleDuration("OrgDomain"), errorCount}}, - &UserMembership{handler: handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount}, - orgEvents: repos.OrgEvents, projectEvents: repos.ProjectEvents}, - &MachineKeys{handler: handler{view, bulkLimit, configs.cycleDuration("MachineKeys"), errorCount}}, - &IDPConfig{handler: handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount}}, - &LoginPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount}}, - &LabelPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount}}, - &IDPProvider{handler: handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount}, - systemDefaults: defaults, iamEvents: repos.IamEvents, orgEvents: repos.OrgEvents}, - &ExternalIDP{handler: handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount}, - systemDefaults: defaults, iamEvents: repos.IamEvents, orgEvents: repos.OrgEvents}, - &PasswordComplexityPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount}}, - &PasswordAgePolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordAgePolicy"), errorCount}}, - &PasswordLockoutPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("PasswordLockoutPolicy"), errorCount}}, - &OrgIAMPolicy{handler: handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount}}, + newProject( + handler{view, bulkLimit, configs.cycleDuration("Project"), errorCount, es}), + newProjectGrant( + handler{view, bulkLimit, configs.cycleDuration("ProjectGrant"), errorCount, es}, + repos.ProjectEvents, + repos.OrgEvents), + newProjectRole(handler{view, bulkLimit, configs.cycleDuration("ProjectRole"), errorCount, es}, + repos.ProjectEvents), + newProjectMember(handler{view, bulkLimit, configs.cycleDuration("ProjectMember"), errorCount, es}, + repos.UserEvents), + newProjectGrantMember(handler{view, bulkLimit, configs.cycleDuration("ProjectGrantMember"), errorCount, es}, + repos.UserEvents), + newApplication(handler{view, bulkLimit, configs.cycleDuration("Application"), errorCount, es}, + repos.ProjectEvents), + newUser(handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es}, + repos.OrgEvents, + repos.IamEvents, + defaults.IamID), + newUserGrant(handler{view, bulkLimit, configs.cycleDuration("UserGrant"), errorCount, es}, + repos.ProjectEvents, + repos.UserEvents, + repos.OrgEvents), + newOrg( + handler{view, bulkLimit, configs.cycleDuration("Org"), errorCount, es}), + newOrgMember( + handler{view, bulkLimit, configs.cycleDuration("OrgMember"), errorCount, es}, + repos.UserEvents), + newOrgDomain( + handler{view, bulkLimit, configs.cycleDuration("OrgDomain"), errorCount, es}), + newUserMembership( + handler{view, bulkLimit, configs.cycleDuration("UserMembership"), errorCount, es}, + repos.OrgEvents, + repos.ProjectEvents), + newMachineKeys( + handler{view, bulkLimit, configs.cycleDuration("MachineKeys"), errorCount, es}), + newIDPConfig( + handler{view, bulkLimit, configs.cycleDuration("IDPConfig"), errorCount, es}), + newLoginPolicy( + handler{view, bulkLimit, configs.cycleDuration("LoginPolicy"), errorCount, es}), + newLabelPolicy( + handler{view, bulkLimit, configs.cycleDuration("LabelPolicy"), errorCount, es}), + newIDPProvider( + handler{view, bulkLimit, configs.cycleDuration("IDPProvider"), errorCount, es}, + + defaults, + repos.IamEvents, + repos.OrgEvents), + newExternalIDP( + handler{view, bulkLimit, configs.cycleDuration("ExternalIDP"), errorCount, es}, + + defaults, + repos.IamEvents, + repos.OrgEvents), + newPasswordComplexityPolicy( + handler{view, bulkLimit, configs.cycleDuration("PasswordComplexityPolicy"), errorCount, es}), + newPasswordAgePolicy( + handler{view, bulkLimit, configs.cycleDuration("PasswordAgePolicy"), errorCount, es}), + newPasswordLockoutPolicy( + handler{view, bulkLimit, configs.cycleDuration("PasswordLockoutPolicy"), errorCount, es}), + newOrgIAMPolicy( + handler{view, bulkLimit, configs.cycleDuration("OrgIAMPolicy"), errorCount, es}), } } func (configs Configs) cycleDuration(viewModel string) time.Duration { c, ok := configs[viewModel] if !ok { - return 1 * time.Second + return 3 * time.Minute } return c.MinimumCycleDuration.Duration } diff --git a/internal/management/repository/eventsourcing/handler/idp_config.go b/internal/management/repository/eventsourcing/handler/idp_config.go index 07301c71b8..5fa73038e5 100644 --- a/internal/management/repository/eventsourcing/handler/idp_config.go +++ b/internal/management/repository/eventsourcing/handler/idp_config.go @@ -2,8 +2,10 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/model" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" @@ -11,29 +13,61 @@ import ( "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type IDPConfig struct { - handler -} - const ( idpConfigTable = "management.idp_configs" ) +type IDPConfig struct { + handler + subscription *eventstore.Subscription +} + +func newIDPConfig(handler handler) *IDPConfig { + h := &IDPConfig{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *IDPConfig) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (m *IDPConfig) ViewModel() string { return idpConfigTable } -func (m *IDPConfig) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestIDPConfigSequence() +func (_ *IDPConfig) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (m *IDPConfig) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := m.view.GetLatestIDPConfigSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (m *IDPConfig) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := m.view.GetLatestIDPConfigSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *IDPConfig) Reduce(event *models.Event) (err error) { +func (m *IDPConfig) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.OrgAggregate: err = m.processIdpConfig(iam_model.IDPProviderTypeOrg, event) @@ -43,7 +77,7 @@ func (m *IDPConfig) Reduce(event *models.Event) (err error) { return err } -func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, event *models.Event) (err error) { +func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, event *es_models.Event) (err error) { idp := new(iam_view_model.IDPConfigView) switch event.Type { case model.IDPConfigAdded, @@ -66,17 +100,17 @@ func (m *IDPConfig) processIdpConfig(providerType iam_model.IDPProviderType, eve if err != nil { return err } - return m.view.DeleteIDPConfig(idp.IDPConfigID, event.Sequence, event.CreationDate) + return m.view.DeleteIDPConfig(idp.IDPConfigID, event) default: - return m.view.ProcessedIDPConfigSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedIDPConfigSequence(event) } if err != nil { return err } - return m.view.PutIDPConfig(idp, idp.Sequence, event.CreationDate) + return m.view.PutIDPConfig(idp, event) } -func (i *IDPConfig) OnError(event *models.Event, err error) error { +func (i *IDPConfig) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Nxu8s", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp config handler") return spooler.HandleError(event, err, i.view.GetLatestIDPConfigFailedEvent, i.view.ProcessedIDPConfigFailedEvent, i.view.ProcessedIDPConfigSequence, i.errorCountUntilSkip) } diff --git a/internal/management/repository/eventsourcing/handler/idp_providers.go b/internal/management/repository/eventsourcing/handler/idp_providers.go index 9d873eed67..1b5933917b 100644 --- a/internal/management/repository/eventsourcing/handler/idp_providers.go +++ b/internal/management/repository/eventsourcing/handler/idp_providers.go @@ -2,18 +2,23 @@ package handler import ( "context" + "github.com/caos/logging" "github.com/caos/zitadel/internal/config/systemdefaults" - "github.com/caos/zitadel/internal/iam/repository/eventsourcing" - org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing" - org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" - - "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/model" + "github.com/caos/zitadel/internal/iam/repository/eventsourcing" "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model" + org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing" + org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" +) + +const ( + idpProviderTable = "management.idp_providers" ) type IDPProvider struct { @@ -21,27 +26,63 @@ type IDPProvider struct { systemDefaults systemdefaults.SystemDefaults iamEvents *eventsourcing.IAMEventstore orgEvents *org_es.OrgEventstore + subscription *eventstore.Subscription } -const ( - idpProviderTable = "management.idp_providers" -) +func newIDPProvider( + handler handler, + systemDefaults systemdefaults.SystemDefaults, + iamEvents *eventsourcing.IAMEventstore, + orgEvents *org_es.OrgEventstore, +) *IDPProvider { + h := &IDPProvider{ + handler: handler, + systemDefaults: systemDefaults, + iamEvents: iamEvents, + orgEvents: orgEvents, + } + + h.subscribe() + + return h +} + +func (m *IDPProvider) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} func (m *IDPProvider) ViewModel() string { return idpProviderTable } -func (m *IDPProvider) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestIDPProviderSequence() +func (_ *IDPProvider) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.IAMAggregate, org_es_model.OrgAggregate} +} + +func (m *IDPProvider) CurrentSequence(event *es_models.Event) (uint64, error) { + sequence, err := m.view.GetLatestIDPProviderSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (m *IDPProvider) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := m.view.GetLatestIDPProviderSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.IAMAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *IDPProvider) Reduce(event *models.Event) (err error) { +func (m *IDPProvider) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.IAMAggregate, org_es_model.OrgAggregate: err = m.processIdpProvider(event) @@ -49,7 +90,7 @@ func (m *IDPProvider) Reduce(event *models.Event) (err error) { return err } -func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { +func (m *IDPProvider) processIdpProvider(event *es_models.Event) (err error) { provider := new(iam_view_model.IDPProviderView) switch event.Type { case model.LoginPolicyIDPProviderAdded, org_es_model.LoginPolicyIDPProviderAdded: @@ -64,7 +105,7 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { if err != nil { return err } - return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event.Sequence, event.CreationDate) + return m.view.DeleteIDPProvider(event.AggregateID, provider.IDPConfigID, event) case model.IDPConfigChanged, org_es_model.IDPConfigChanged: esConfig := new(iam_view_model.IDPConfigView) providerType := iam_model.IDPProviderTypeSystem @@ -88,16 +129,16 @@ func (m *IDPProvider) processIdpProvider(event *models.Event) (err error) { for _, provider := range providers { m.fillConfigData(provider, config) } - return m.view.PutIDPProviders(event.Sequence, event.CreationDate, providers...) + return m.view.PutIDPProviders(event, providers...) case org_es_model.LoginPolicyRemoved: - return m.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteIDPProvidersByAggregateID(event.AggregateID, event) default: - return m.view.ProcessedIDPProviderSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedIDPProviderSequence(event) } if err != nil { return err } - return m.view.PutIDPProvider(provider, provider.Sequence, event.CreationDate) + return m.view.PutIDPProvider(provider, event) } func (m *IDPProvider) fillData(provider *iam_view_model.IDPProviderView) (err error) { @@ -121,7 +162,7 @@ func (m *IDPProvider) fillConfigData(provider *iam_view_model.IDPProviderView, c provider.IDPState = int32(config.State) } -func (m *IDPProvider) OnError(event *models.Event, err error) error { +func (m *IDPProvider) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Msj8c", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") return spooler.HandleError(event, err, m.view.GetLatestIDPProviderFailedEvent, m.view.ProcessedIDPProviderFailedEvent, m.view.ProcessedIDPProviderSequence, m.errorCountUntilSkip) } diff --git a/internal/management/repository/eventsourcing/handler/label_policy.go b/internal/management/repository/eventsourcing/handler/label_policy.go index 2c47a03c80..2cc3ba833e 100644 --- a/internal/management/repository/eventsourcing/handler/label_policy.go +++ b/internal/management/repository/eventsourcing/handler/label_policy.go @@ -2,34 +2,67 @@ package handler import ( "github.com/caos/logging" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type LabelPolicy struct { - handler -} - const ( labelPolicyTable = "management.label_policies" ) +type LabelPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newLabelPolicy(handler handler) *LabelPolicy { + h := &LabelPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *LabelPolicy) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (m *LabelPolicy) ViewModel() string { return labelPolicyTable } +func (_ *LabelPolicy) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (m *LabelPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := m.view.GetLatestLabelPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (m *LabelPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestLabelPolicySequence() + sequence, err := m.view.GetLatestLabelPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -53,12 +86,12 @@ func (m *LabelPolicy) processLabelPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) default: - return m.view.ProcessedLabelPolicySequence(event.Sequence, event.CreationDate) + return m.view.ProcessedLabelPolicySequence(event) } if err != nil { return err } - return m.view.PutLabelPolicy(policy, policy.Sequence, event.CreationDate) + return m.view.PutLabelPolicy(policy, event) } func (m *LabelPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/login_policy.go b/internal/management/repository/eventsourcing/handler/login_policy.go index cb6f06c4d2..cf8994ff1e 100644 --- a/internal/management/repository/eventsourcing/handler/login_policy.go +++ b/internal/management/repository/eventsourcing/handler/login_policy.go @@ -2,34 +2,67 @@ package handler import ( "github.com/caos/logging" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type LoginPolicy struct { - handler -} - const ( loginPolicyTable = "management.login_policies" ) +type LoginPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newLoginPolicy(handler handler) *LoginPolicy { + h := &LoginPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *LoginPolicy) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (m *LoginPolicy) ViewModel() string { return loginPolicyTable } +func (_ *LoginPolicy) AggregateTypes() []models.AggregateType { + return []models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (m *LoginPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := m.view.GetLatestLoginPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (m *LoginPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestLoginPolicySequence() + sequence, err := m.view.GetLatestLoginPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -57,14 +90,14 @@ func (m *LoginPolicy) processLoginPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) case model.LoginPolicyRemoved: - return m.view.DeleteLoginPolicy(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteLoginPolicy(event.AggregateID, event) default: - return m.view.ProcessedLoginPolicySequence(event.Sequence, event.CreationDate) + return m.view.ProcessedLoginPolicySequence(event) } if err != nil { return err } - return m.view.PutLoginPolicy(policy, policy.Sequence, event.CreationDate) + return m.view.PutLoginPolicy(policy, event) } func (m *LoginPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/machine_keys.go b/internal/management/repository/eventsourcing/handler/machine_keys.go index cd6b29b6a8..6758c4f173 100644 --- a/internal/management/repository/eventsourcing/handler/machine_keys.go +++ b/internal/management/repository/eventsourcing/handler/machine_keys.go @@ -4,33 +4,66 @@ import ( "time" "github.com/caos/logging" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" usr_model "github.com/caos/zitadel/internal/user/repository/view/model" ) -type MachineKeys struct { - handler -} - const ( machineKeysTable = "management.machine_keys" ) +type MachineKeys struct { + handler + subscription *eventstore.Subscription +} + +func newMachineKeys(handler handler) *MachineKeys { + h := &MachineKeys{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *MachineKeys) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (d *MachineKeys) ViewModel() string { return machineKeysTable } +func (_ *MachineKeys) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.UserAggregate} +} + +func (k *MachineKeys) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := k.view.GetLatestMachineKeySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (d *MachineKeys) EventQuery() (*models.SearchQuery, error) { - sequence, err := d.view.GetLatestMachineKeySequence() + sequence, err := d.view.GetLatestMachineKeySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.UserAggregate). + AggregateTypeFilter(d.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -48,23 +81,23 @@ func (d *MachineKeys) processMachineKeys(event *models.Event) (err error) { case model.MachineKeyAdded: err = key.AppendEvent(event) if key.ExpirationDate.Before(time.Now()) { - return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate) + return d.view.ProcessedMachineKeySequence(event) } case model.MachineKeyRemoved: err = key.SetData(event) if err != nil { return err } - return d.view.DeleteMachineKey(key.ID, event.Sequence, event.CreationDate) + return d.view.DeleteMachineKey(key.ID, event) case model.UserRemoved: - return d.view.DeleteMachineKeysByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return d.view.DeleteMachineKeysByUserID(event.AggregateID, event) default: - return d.view.ProcessedMachineKeySequence(event.Sequence, event.CreationDate) + return d.view.ProcessedMachineKeySequence(event) } if err != nil { return err } - return d.view.PutMachineKey(key, key.Sequence, event.CreationDate) + return d.view.PutMachineKey(key, event) } func (d *MachineKeys) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/org.go b/internal/management/repository/eventsourcing/handler/org.go index 23155a5c52..a4f6eb211d 100644 --- a/internal/management/repository/eventsourcing/handler/org.go +++ b/internal/management/repository/eventsourcing/handler/org.go @@ -2,28 +2,62 @@ package handler import ( "github.com/caos/logging" - + "github.com/caos/zitadel/internal/eventstore" + "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/org/repository/eventsourcing" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" org_model "github.com/caos/zitadel/internal/org/repository/view/model" ) -type Org struct { - handler -} - const ( orgTable = "management.orgs" ) +type Org struct { + handler + subscription *eventstore.Subscription +} + +func newOrg(handler handler) *Org { + h := &Org{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *Org) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (o *Org) ViewModel() string { return orgTable } +func (_ *Org) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate} +} + +func (o *Org) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := o.view.GetLatestOrgSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (o *Org) EventQuery() (*es_models.SearchQuery, error) { - sequence, err := o.view.GetLatestOrgSequence() + sequence, err := o.view.GetLatestOrgSequence("") if err != nil { return nil, err } @@ -47,12 +81,12 @@ func (o *Org) Reduce(event *es_models.Event) (err error) { } err = org.AppendEvent(event) default: - return o.view.ProcessedOrgSequence(event.Sequence, event.CreationDate) + return o.view.ProcessedOrgSequence(event) } if err != nil { return err } - return o.view.PutOrg(org, event.CreationDate) + return o.view.PutOrg(org, event) } func (o *Org) OnError(event *es_models.Event, spoolerErr error) error { diff --git a/internal/management/repository/eventsourcing/handler/org_domain.go b/internal/management/repository/eventsourcing/handler/org_domain.go index 9dc6307749..9a7dedb5ee 100644 --- a/internal/management/repository/eventsourcing/handler/org_domain.go +++ b/internal/management/repository/eventsourcing/handler/org_domain.go @@ -2,33 +2,66 @@ package handler import ( "github.com/caos/logging" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" org_model "github.com/caos/zitadel/internal/org/repository/view/model" ) -type OrgDomain struct { - handler -} - const ( orgDomainTable = "management.org_domains" ) +type OrgDomain struct { + handler + subscription *eventstore.Subscription +} + +func newOrgDomain(handler handler) *OrgDomain { + h := &OrgDomain{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *OrgDomain) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (d *OrgDomain) ViewModel() string { return orgDomainTable } +func (_ *OrgDomain) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate} +} + +func (p *OrgDomain) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestOrgDomainSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (d *OrgDomain) EventQuery() (*models.SearchQuery, error) { - sequence, err := d.view.GetLatestOrgDomainSequence() + sequence, err := d.view.GetLatestOrgDomainSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate). + AggregateTypeFilter(d.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -72,7 +105,7 @@ func (d *OrgDomain) processOrgDomain(event *models.Event) (err error) { for _, existingDomain := range existingDomains { existingDomain.Primary = false } - err = d.view.PutOrgDomains(existingDomains, 0, event.CreationDate) + err = d.view.PutOrgDomains(existingDomains, event) if err != nil { return err } @@ -82,14 +115,14 @@ func (d *OrgDomain) processOrgDomain(event *models.Event) (err error) { if err != nil { return err } - return d.view.DeleteOrgDomain(event.AggregateID, domain.Domain, event.Sequence, event.CreationDate) + return d.view.DeleteOrgDomain(event.AggregateID, domain.Domain, event) default: - return d.view.ProcessedOrgDomainSequence(event.Sequence, event.CreationDate) + return d.view.ProcessedOrgDomainSequence(event) } if err != nil { return err } - return d.view.PutOrgDomain(domain, domain.Sequence, event.CreationDate) + return d.view.PutOrgDomain(domain, event) } func (d *OrgDomain) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/org_iam_policy.go b/internal/management/repository/eventsourcing/handler/org_iam_policy.go index fffe08cfec..796652bbb4 100644 --- a/internal/management/repository/eventsourcing/handler/org_iam_policy.go +++ b/internal/management/repository/eventsourcing/handler/org_iam_policy.go @@ -2,34 +2,67 @@ package handler import ( "github.com/caos/logging" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type OrgIAMPolicy struct { - handler -} - const ( orgIAMPolicyTable = "management.org_iam_policies" ) +type OrgIAMPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newOrgIAMPolicy(handler handler) *OrgIAMPolicy { + h := &OrgIAMPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *OrgIAMPolicy) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (m *OrgIAMPolicy) ViewModel() string { return orgIAMPolicyTable } +func (_ *OrgIAMPolicy) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *OrgIAMPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestOrgIAMPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (m *OrgIAMPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestOrgIAMPolicySequence() + sequence, err := m.view.GetLatestOrgIAMPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -53,14 +86,14 @@ func (m *OrgIAMPolicy) processOrgIAMPolicy(event *models.Event) (err error) { } err = policy.AppendEvent(event) case model.OrgIAMPolicyRemoved: - return m.view.DeleteOrgIAMPolicy(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteOrgIAMPolicy(event.AggregateID, event) default: - return m.view.ProcessedOrgIAMPolicySequence(event.Sequence, event.CreationDate) + return m.view.ProcessedOrgIAMPolicySequence(event) } if err != nil { return err } - return m.view.PutOrgIAMPolicy(policy, policy.Sequence, event.CreationDate) + return m.view.PutOrgIAMPolicy(policy, event) } func (m *OrgIAMPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/org_member.go b/internal/management/repository/eventsourcing/handler/org_member.go index 26f2b2fb86..cf3e1b6499 100644 --- a/internal/management/repository/eventsourcing/handler/org_member.go +++ b/internal/management/repository/eventsourcing/handler/org_member.go @@ -4,9 +4,10 @@ import ( "context" "github.com/caos/logging" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" org_model "github.com/caos/zitadel/internal/org/repository/view/model" @@ -15,26 +16,62 @@ import ( usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" ) -type OrgMember struct { - handler - userEvents *usr_event.UserEventstore -} - const ( orgMemberTable = "management.org_members" ) +type OrgMember struct { + handler + userEvents *usr_event.UserEventstore + subscription *eventstore.Subscription +} + +func newOrgMember( + handler handler, + userEvents *usr_event.UserEventstore, +) *OrgMember { + h := &OrgMember{ + handler: handler, + userEvents: userEvents, + } + + h.subscribe() + + return h +} + +func (m *OrgMember) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (m *OrgMember) ViewModel() string { return orgMemberTable } +func (_ *OrgMember) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate, usr_es_model.UserAggregate} +} + +func (p *OrgMember) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestOrgMemberSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (m *OrgMember) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestOrgMemberSequence() + sequence, err := m.view.GetLatestOrgMemberSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, usr_es_model.UserAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -72,14 +109,14 @@ func (m *OrgMember) processOrgMember(event *models.Event) (err error) { if err != nil { return err } - return m.view.DeleteOrgMember(event.AggregateID, member.UserID, event.Sequence, event.CreationDate) + return m.view.DeleteOrgMember(event.AggregateID, member.UserID, event) default: - return m.view.ProcessedOrgMemberSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedOrgMemberSequence(event) } if err != nil { return err } - return m.view.PutOrgMember(member, member.Sequence, event.CreationDate) + return m.view.PutOrgMember(member, event) } func (m *OrgMember) processUser(event *models.Event) (err error) { @@ -94,7 +131,7 @@ func (m *OrgMember) processUser(event *models.Event) (err error) { return err } if len(members) == 0 { - return m.view.ProcessedOrgMemberSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedOrgMemberSequence(event) } user, err := m.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -103,13 +140,12 @@ func (m *OrgMember) processUser(event *models.Event) (err error) { for _, member := range members { m.fillUserData(member, user) } - return m.view.PutOrgMembers(members, event.Sequence, event.CreationDate) + return m.view.PutOrgMembers(members, event) case usr_es_model.UserRemoved: - return m.view.DeleteOrgMembersByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteOrgMembersByUserID(event.AggregateID, event) default: - return m.view.ProcessedOrgMemberSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedOrgMemberSequence(event) } - return nil } func (m *OrgMember) fillData(member *org_model.OrgMemberView) (err error) { diff --git a/internal/management/repository/eventsourcing/handler/password_age_policy.go b/internal/management/repository/eventsourcing/handler/password_age_policy.go index 535acf03db..eee2e2711c 100644 --- a/internal/management/repository/eventsourcing/handler/password_age_policy.go +++ b/internal/management/repository/eventsourcing/handler/password_age_policy.go @@ -2,34 +2,67 @@ package handler import ( "github.com/caos/logging" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type PasswordAgePolicy struct { - handler -} - const ( passwordAgePolicyTable = "management.password_age_policies" ) +type PasswordAgePolicy struct { + handler + subscription *eventstore.Subscription +} + +func newPasswordAgePolicy(handler handler) *PasswordAgePolicy { + h := &PasswordAgePolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *PasswordAgePolicy) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (m *PasswordAgePolicy) ViewModel() string { return passwordAgePolicyTable } -func (m *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestPasswordAgePolicySequence() +func (_ *PasswordAgePolicy) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (o *PasswordAgePolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := o.view.GetLatestPasswordAgePolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (p *PasswordAgePolicy) EventQuery() (*models.SearchQuery, error) { + sequence, err := p.view.GetLatestPasswordAgePolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -53,14 +86,14 @@ func (m *PasswordAgePolicy) processPasswordAgePolicy(event *models.Event) (err e } err = policy.AppendEvent(event) case model.PasswordAgePolicyRemoved: - return m.view.DeletePasswordAgePolicy(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeletePasswordAgePolicy(event.AggregateID, event) default: - return m.view.ProcessedPasswordAgePolicySequence(event.Sequence, event.CreationDate) + return m.view.ProcessedPasswordAgePolicySequence(event) } if err != nil { return err } - return m.view.PutPasswordAgePolicy(policy, policy.Sequence, event.CreationDate) + return m.view.PutPasswordAgePolicy(policy, event) } func (m *PasswordAgePolicy) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/password_complexity_policy.go b/internal/management/repository/eventsourcing/handler/password_complexity_policy.go index 4ada8b0c95..d2d14c885d 100644 --- a/internal/management/repository/eventsourcing/handler/password_complexity_policy.go +++ b/internal/management/repository/eventsourcing/handler/password_complexity_policy.go @@ -2,34 +2,67 @@ package handler import ( "github.com/caos/logging" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" - + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type PasswordComplexityPolicy struct { - handler -} - const ( passwordComplexityPolicyTable = "management.password_complexity_policies" ) +type PasswordComplexityPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newPasswordComplexityPolicy(handler handler) *PasswordComplexityPolicy { + h := &PasswordComplexityPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *PasswordComplexityPolicy) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (p *PasswordComplexityPolicy) ViewModel() string { return passwordComplexityPolicyTable } +func (_ *PasswordComplexityPolicy) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *PasswordComplexityPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *PasswordComplexityPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestPasswordComplexityPolicySequence() + sequence, err := p.view.GetLatestPasswordComplexityPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -53,14 +86,14 @@ func (p *PasswordComplexityPolicy) processPasswordComplexityPolicy(event *models } err = policy.AppendEvent(event) case model.PasswordComplexityPolicyRemoved: - return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event.Sequence, event.CreationDate) + return p.view.DeletePasswordComplexityPolicy(event.AggregateID, event) default: - return p.view.ProcessedPasswordComplexityPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedPasswordComplexityPolicySequence(event) } if err != nil { return err } - return p.view.PutPasswordComplexityPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutPasswordComplexityPolicy(policy, event) } func (p *PasswordComplexityPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/password_lockout_policy.go b/internal/management/repository/eventsourcing/handler/password_lockout_policy.go index c5a66d9528..19e7c9c0b6 100644 --- a/internal/management/repository/eventsourcing/handler/password_lockout_policy.go +++ b/internal/management/repository/eventsourcing/handler/password_lockout_policy.go @@ -2,34 +2,68 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" iam_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" ) -type PasswordLockoutPolicy struct { - handler -} - const ( passwordLockoutPolicyTable = "management.password_lockout_policies" ) +type PasswordLockoutPolicy struct { + handler + subscription *eventstore.Subscription +} + +func newPasswordLockoutPolicy(handler handler) *PasswordLockoutPolicy { + h := &PasswordLockoutPolicy{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *PasswordLockoutPolicy) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (p *PasswordLockoutPolicy) ViewModel() string { return passwordLockoutPolicyTable } +func (_ *PasswordLockoutPolicy) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.OrgAggregate, iam_es_model.IAMAggregate} +} + +func (p *PasswordLockoutPolicy) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestPasswordLockoutPolicySequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *PasswordLockoutPolicy) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestPasswordLockoutPolicySequence() + sequence, err := p.view.GetLatestPasswordLockoutPolicySequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.OrgAggregate, iam_es_model.IAMAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -53,14 +87,14 @@ func (p *PasswordLockoutPolicy) processPasswordLockoutPolicy(event *models.Event } err = policy.AppendEvent(event) case model.PasswordLockoutPolicyRemoved: - return p.view.DeletePasswordLockoutPolicy(event.AggregateID, event.Sequence, event.CreationDate) + return p.view.DeletePasswordLockoutPolicy(event.AggregateID, event) default: - return p.view.ProcessedPasswordLockoutPolicySequence(event.Sequence, event.CreationDate) + return p.view.ProcessedPasswordLockoutPolicySequence(event) } if err != nil { return err } - return p.view.PutPasswordLockoutPolicy(policy, policy.Sequence, event.CreationDate) + return p.view.PutPasswordLockoutPolicy(policy, event) } func (p *PasswordLockoutPolicy) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/project.go b/internal/management/repository/eventsourcing/handler/project.go index 0536de9ae5..51331d44ee 100644 --- a/internal/management/repository/eventsourcing/handler/project.go +++ b/internal/management/repository/eventsourcing/handler/project.go @@ -5,27 +5,59 @@ import ( "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" view_model "github.com/caos/zitadel/internal/project/repository/view/model" ) -type Project struct { - handler - eventstore eventstore.Eventstore -} - const ( projectTable = "management.projects" ) +type Project struct { + handler + subscription *eventstore.Subscription +} + +func newProject(handler handler) *Project { + h := &Project{ + handler: handler, + } + + h.subscribe() + + return h +} + +func (m *Project) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (p *Project) ViewModel() string { return projectTable } +func (_ *Project) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.ProjectAggregate} +} + +func (p *Project) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestProjectSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *Project) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestProjectSequence() + sequence, err := p.view.GetLatestProjectSequence("") if err != nil { return nil, err } @@ -46,14 +78,14 @@ func (p *Project) Reduce(event *models.Event) (err error) { } err = project.AppendEvent(event) case es_model.ProjectRemoved: - return p.view.DeleteProject(event.AggregateID, event.Sequence, event.CreationDate) + return p.view.DeleteProject(event.AggregateID, event) default: - return p.view.ProcessedProjectSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectSequence(event) } if err != nil { return err } - return p.view.PutProject(project, event.CreationDate) + return p.view.PutProject(project, event) } func (p *Project) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/project_grant.go b/internal/management/repository/eventsourcing/handler/project_grant.go index 1c7306bb21..b01898bb29 100644 --- a/internal/management/repository/eventsourcing/handler/project_grant.go +++ b/internal/management/repository/eventsourcing/handler/project_grant.go @@ -2,12 +2,12 @@ package handler import ( "context" - "time" "github.com/caos/logging" "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" org_model "github.com/caos/zitadel/internal/org/model" org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing" @@ -17,23 +17,60 @@ import ( view_model "github.com/caos/zitadel/internal/project/repository/view/model" ) -type ProjectGrant struct { - handler - eventstore eventstore.Eventstore - projectEvents *proj_event.ProjectEventstore - orgEvents *org_event.OrgEventstore -} - const ( grantedProjectTable = "management.project_grants" ) +type ProjectGrant struct { + handler + projectEvents *proj_event.ProjectEventstore + orgEvents *org_event.OrgEventstore + subscription *eventstore.Subscription +} + +func newProjectGrant( + handler handler, + projectEvents *proj_event.ProjectEventstore, + orgEvents *org_event.OrgEventstore, +) *ProjectGrant { + h := &ProjectGrant{ + handler: handler, + projectEvents: projectEvents, + orgEvents: orgEvents, + } + + h.subscribe() + + return h +} + +func (m *ProjectGrant) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (p *ProjectGrant) ViewModel() string { return grantedProjectTable } +func (_ *ProjectGrant) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.ProjectAggregate} +} + +func (p *ProjectGrant) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestProjectGrantSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *ProjectGrant) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestProjectGrantSequence() + sequence, err := p.view.GetLatestProjectGrantSequence("") if err != nil { return nil, err } @@ -48,7 +85,7 @@ func (p *ProjectGrant) Reduce(event *models.Event) (err error) { if err != nil { return err } - return p.updateExistingProjects(project, event.Sequence, event.CreationDate) + return p.updateExistingProjects(project, event) case es_model.ProjectGrantAdded: err = grantedProject.AppendEvent(event) if err != nil { @@ -86,16 +123,16 @@ func (p *ProjectGrant) Reduce(event *models.Event) (err error) { if err != nil { return err } - return p.view.DeleteProjectGrant(grant.GrantID, event.Sequence, event.CreationDate) + return p.view.DeleteProjectGrant(grant.GrantID, event) case es_model.ProjectRemoved: return p.view.DeleteProjectGrantsByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectGrantSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectGrantSequence(event) } if err != nil { return err } - return p.view.PutProjectGrant(grantedProject, event.CreationDate) + return p.view.PutProjectGrant(grantedProject, event) } func (p *ProjectGrant) fillOrgData(grantedProject *view_model.ProjectGrantView, org, resourceOwner *org_model.Org) { @@ -107,7 +144,7 @@ func (p *ProjectGrant) getProject(projectID string) (*proj_model.Project, error) return p.projectEvents.ProjectByID(context.Background(), projectID) } -func (p *ProjectGrant) updateExistingProjects(project *view_model.ProjectView, sequence uint64, eventTimestamp time.Time) error { +func (p *ProjectGrant) updateExistingProjects(project *view_model.ProjectView, event *models.Event) error { projectGrants, err := p.view.ProjectGrantsByProjectID(project.ProjectID) if err != nil { logging.LogWithFields("SPOOL-los03", "id", project.ProjectID).WithError(err).Warn("could not update existing projects") @@ -115,7 +152,7 @@ func (p *ProjectGrant) updateExistingProjects(project *view_model.ProjectView, s for _, existingGrant := range projectGrants { existingGrant.Name = project.Name } - return p.view.PutProjectGrants(projectGrants, sequence, eventTimestamp) + return p.view.PutProjectGrants(projectGrants, event) } func (p *ProjectGrant) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/project_grant_member.go b/internal/management/repository/eventsourcing/handler/project_grant_member.go index fb37af782e..c00eb64763 100644 --- a/internal/management/repository/eventsourcing/handler/project_grant_member.go +++ b/internal/management/repository/eventsourcing/handler/project_grant_member.go @@ -5,8 +5,10 @@ import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" view_model "github.com/caos/zitadel/internal/project/repository/view/model" @@ -15,26 +17,62 @@ import ( usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" ) -type ProjectGrantMember struct { - handler - userEvents *usr_event.UserEventstore -} - const ( projectGrantMemberTable = "management.project_grant_members" ) +type ProjectGrantMember struct { + handler + userEvents *usr_event.UserEventstore + subscription *eventstore.Subscription +} + +func newProjectGrantMember( + handler handler, + userEvents *usr_event.UserEventstore, +) *ProjectGrantMember { + h := &ProjectGrantMember{ + handler: handler, + userEvents: userEvents, + } + + h.subscribe() + + return h +} + +func (m *ProjectGrantMember) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (p *ProjectGrantMember) ViewModel() string { return projectGrantMemberTable } +func (_ *ProjectGrantMember) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{proj_es_model.ProjectAggregate, usr_es_model.UserAggregate} +} + +func (p *ProjectGrantMember) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestProjectGrantMemberSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *ProjectGrantMember) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestProjectGrantMemberSequence() + sequence, err := p.view.GetLatestProjectGrantMemberSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(proj_es_model.ProjectAggregate, usr_es_model.UserAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -72,16 +110,16 @@ func (p *ProjectGrantMember) processProjectGrantMember(event *models.Event) (err if err != nil { return err } - return p.view.DeleteProjectGrantMember(member.GrantID, member.UserID, event.Sequence, event.CreationDate) + return p.view.DeleteProjectGrantMember(member.GrantID, member.UserID, event) case proj_es_model.ProjectRemoved: return p.view.DeleteProjectGrantMembersByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectGrantMemberSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectGrantMemberSequence(event) } if err != nil { return err } - return p.view.PutProjectGrantMember(member, member.Sequence, event.CreationDate) + return p.view.PutProjectGrantMember(member, event) } func (p *ProjectGrantMember) processUser(event *models.Event) (err error) { @@ -96,7 +134,7 @@ func (p *ProjectGrantMember) processUser(event *models.Event) (err error) { return err } if len(members) == 0 { - return p.view.ProcessedProjectGrantMemberSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectGrantMemberSequence(event) } user, err := p.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -105,11 +143,10 @@ func (p *ProjectGrantMember) processUser(event *models.Event) (err error) { for _, member := range members { p.fillUserData(member, user) } - return p.view.PutProjectGrantMembers(members, event.Sequence, event.CreationDate) + return p.view.PutProjectGrantMembers(members, event) default: - return p.view.ProcessedProjectGrantMemberSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectGrantMemberSequence(event) } - return nil } func (p *ProjectGrantMember) fillData(member *view_model.ProjectGrantMemberView) (err error) { diff --git a/internal/management/repository/eventsourcing/handler/project_member.go b/internal/management/repository/eventsourcing/handler/project_member.go index 7de3603f25..721f42e9d8 100644 --- a/internal/management/repository/eventsourcing/handler/project_member.go +++ b/internal/management/repository/eventsourcing/handler/project_member.go @@ -5,8 +5,10 @@ import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" view_model "github.com/caos/zitadel/internal/project/repository/view/model" @@ -15,26 +17,62 @@ import ( usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" ) -type ProjectMember struct { - handler - userEvents *usr_event.UserEventstore -} - const ( projectMemberTable = "management.project_members" ) +type ProjectMember struct { + handler + userEvents *usr_event.UserEventstore + subscription *eventstore.Subscription +} + +func newProjectMember( + handler handler, + userEvents *usr_event.UserEventstore, +) *ProjectMember { + h := &ProjectMember{ + handler: handler, + userEvents: userEvents, + } + + h.subscribe() + + return h +} + +func (m *ProjectMember) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (p *ProjectMember) ViewModel() string { return projectMemberTable } +func (_ *ProjectMember) AggregateTypes() []models.AggregateType { + return []models.AggregateType{proj_es_model.ProjectAggregate, usr_es_model.UserAggregate} +} + +func (p *ProjectMember) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestProjectMemberSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *ProjectMember) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestProjectMemberSequence() + sequence, err := p.view.GetLatestProjectMemberSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(proj_es_model.ProjectAggregate, usr_es_model.UserAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -72,16 +110,16 @@ func (p *ProjectMember) processProjectMember(event *models.Event) (err error) { if err != nil { return err } - return p.view.DeleteProjectMember(event.AggregateID, member.UserID, event.Sequence, event.CreationDate) + return p.view.DeleteProjectMember(event.AggregateID, member.UserID, event) case proj_es_model.ProjectRemoved: return p.view.DeleteProjectMembersByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectMemberSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectMemberSequence(event) } if err != nil { return err } - return p.view.PutProjectMember(member, member.Sequence, event.CreationDate) + return p.view.PutProjectMember(member, event) } func (p *ProjectMember) processUser(event *models.Event) (err error) { @@ -96,7 +134,7 @@ func (p *ProjectMember) processUser(event *models.Event) (err error) { return err } if len(members) == 0 { - return p.view.ProcessedProjectMemberSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectMemberSequence(event) } user, err := p.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -105,9 +143,9 @@ func (p *ProjectMember) processUser(event *models.Event) (err error) { for _, member := range members { p.fillUserData(member, user) } - return p.view.PutProjectMembers(members, event.Sequence, event.CreationDate) + return p.view.PutProjectMembers(members, event) default: - return p.view.ProcessedProjectMemberSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectMemberSequence(event) } return nil } diff --git a/internal/management/repository/eventsourcing/handler/project_role.go b/internal/management/repository/eventsourcing/handler/project_role.go index 0dba4b14e8..3d89ba4a9f 100644 --- a/internal/management/repository/eventsourcing/handler/project_role.go +++ b/internal/management/repository/eventsourcing/handler/project_role.go @@ -3,7 +3,9 @@ package handler import ( "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/project/repository/eventsourcing" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" @@ -11,21 +13,57 @@ import ( view_model "github.com/caos/zitadel/internal/project/repository/view/model" ) -type ProjectRole struct { - handler - projectEvents *proj_event.ProjectEventstore -} - const ( projectRoleTable = "management.project_roles" ) +type ProjectRole struct { + handler + projectEvents *proj_event.ProjectEventstore + subscription *eventstore.Subscription +} + +func newProjectRole( + handler handler, + projectEvents *proj_event.ProjectEventstore, +) *ProjectRole { + h := &ProjectRole{ + handler: handler, + projectEvents: projectEvents, + } + + h.subscribe() + + return h +} + +func (m *ProjectRole) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (p *ProjectRole) ViewModel() string { return projectRoleTable } +func (_ *ProjectRole) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.ProjectAggregate} +} + +func (p *ProjectRole) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := p.view.GetLatestProjectRoleSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (p *ProjectRole) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestProjectRoleSequence() + sequence, err := p.view.GetLatestProjectRoleSequence("") if err != nil { return nil, err } @@ -52,16 +90,16 @@ func (p *ProjectRole) Reduce(event *models.Event) (err error) { if err != nil { return err } - return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event.Sequence, event.CreationDate) + return p.view.DeleteProjectRole(event.AggregateID, event.ResourceOwner, role.Key, event) case es_model.ProjectRemoved: return p.view.DeleteProjectRolesByProjectID(event.AggregateID) default: - return p.view.ProcessedProjectRoleSequence(event.Sequence, event.CreationDate) + return p.view.ProcessedProjectRoleSequence(event) } if err != nil { return err } - return p.view.PutProjectRole(role, event.CreationDate) + return p.view.PutProjectRole(role, event) } func (p *ProjectRole) OnError(event *models.Event, err error) error { diff --git a/internal/management/repository/eventsourcing/handler/user.go b/internal/management/repository/eventsourcing/handler/user.go index 0721e0fcd3..05497a0260 100644 --- a/internal/management/repository/eventsourcing/handler/user.go +++ b/internal/management/repository/eventsourcing/handler/user.go @@ -2,14 +2,14 @@ package handler import ( "context" - iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing" "github.com/caos/logging" - "github.com/caos/zitadel/internal/eventstore" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing" org_model "github.com/caos/zitadel/internal/org/model" org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing" org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" @@ -17,29 +17,68 @@ import ( view_model "github.com/caos/zitadel/internal/user/repository/view/model" ) -type User struct { - handler - eventstore eventstore.Eventstore - orgEvents *org_events.OrgEventstore - iamEvents *iam_es.IAMEventstore - iamID string -} - const ( userTable = "management.users" ) +type User struct { + handler + orgEvents *org_events.OrgEventstore + iamEvents *iam_es.IAMEventstore + iamID string + subscription *eventstore.Subscription +} + +func newUser( + handler handler, + orgEvents *org_events.OrgEventstore, + iamEvents *iam_es.IAMEventstore, + iamID string, +) *User { + h := &User{ + handler: handler, + orgEvents: orgEvents, + iamEvents: iamEvents, + iamID: iamID, + } + + h.subscribe() + + return h +} + +func (m *User) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (u *User) ViewModel() string { return userTable } +func (_ *User) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{es_model.UserAggregate, org_es_model.OrgAggregate} +} + +func (u *User) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := u.view.GetLatestUserSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (u *User) EventQuery() (*models.SearchQuery, error) { - sequence, err := u.view.GetLatestUserSequence() + sequence, err := u.view.GetLatestUserSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(es_model.UserAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(u.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } @@ -115,14 +154,14 @@ func (u *User) ProcessUser(event *models.Event) (err error) { } err = u.fillLoginNames(user) case es_model.UserRemoved: - return u.view.DeleteUser(event.AggregateID, event.Sequence, event.CreationDate) + return u.view.DeleteUser(event.AggregateID, event) default: - return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserSequence(event) } if err != nil { return err } - return u.view.PutUser(user, user.Sequence, event.CreationDate) + return u.view.PutUser(user, event) } func (u *User) ProcessOrg(event *models.Event) (err error) { @@ -136,7 +175,7 @@ func (u *User) ProcessOrg(event *models.Event) (err error) { case org_es_model.OrgDomainPrimarySet: return u.fillPreferredLoginNamesOnOrgUsers(event) default: - return u.view.ProcessedUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserSequence(event) } } @@ -159,7 +198,7 @@ func (u *User) fillLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.SetLoginNames(policy, org.Domains) } - return u.view.PutUsers(users, event.Sequence, event.CreationDate) + return u.view.PutUsers(users, event) } func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { @@ -184,7 +223,7 @@ func (u *User) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { for _, user := range users { user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) } - return u.view.PutUsers(users, event.Sequence, event.CreationDate) + return u.view.PutUsers(users, event) } func (u *User) fillLoginNames(user *view_model.UserView) (err error) { diff --git a/internal/management/repository/eventsourcing/handler/user_external_idps.go b/internal/management/repository/eventsourcing/handler/user_external_idps.go index de57a8f0f2..059a15c9bd 100644 --- a/internal/management/repository/eventsourcing/handler/user_external_idps.go +++ b/internal/management/repository/eventsourcing/handler/user_external_idps.go @@ -2,21 +2,27 @@ package handler import ( "context" + "github.com/caos/logging" "github.com/caos/zitadel/internal/config/systemdefaults" caos_errs "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore" + "github.com/caos/zitadel/internal/eventstore/models" + es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" + "github.com/caos/zitadel/internal/eventstore/spooler" + iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/eventsourcing" + iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model" org_es "github.com/caos/zitadel/internal/org/repository/eventsourcing" org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" usr_view_model "github.com/caos/zitadel/internal/user/repository/view/model" +) - "github.com/caos/zitadel/internal/eventstore/models" - es_models "github.com/caos/zitadel/internal/eventstore/models" - "github.com/caos/zitadel/internal/eventstore/spooler" - iam_model "github.com/caos/zitadel/internal/iam/model" - iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" +const ( + externalIDPTable = "management.user_external_idps" ) type ExternalIDP struct { @@ -24,27 +30,63 @@ type ExternalIDP struct { systemDefaults systemdefaults.SystemDefaults iamEvents *eventsourcing.IAMEventstore orgEvents *org_es.OrgEventstore + subscription *eventstore.Subscription } -const ( - externalIDPTable = "management.user_external_idps" -) +func newExternalIDP( + handler handler, + systemDefaults systemdefaults.SystemDefaults, + iamEvents *eventsourcing.IAMEventstore, + orgEvents *org_es.OrgEventstore, +) *ExternalIDP { + h := &ExternalIDP{ + handler: handler, + systemDefaults: systemDefaults, + iamEvents: iamEvents, + orgEvents: orgEvents, + } + + h.subscribe() + + return h +} + +func (m *ExternalIDP) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} func (i *ExternalIDP) ViewModel() string { return externalIDPTable } -func (i *ExternalIDP) EventQuery() (*models.SearchQuery, error) { - sequence, err := i.view.GetLatestExternalIDPSequence() +func (_ *ExternalIDP) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{model.UserAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate} +} + +func (i *ExternalIDP) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := i.view.GetLatestExternalIDPSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (i *ExternalIDP) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := i.view.GetLatestExternalIDPSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(model.UserAggregate, iam_es_model.IAMAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(i.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (i *ExternalIDP) Reduce(event *models.Event) (err error) { +func (i *ExternalIDP) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case model.UserAggregate: err = i.processUser(event) @@ -54,7 +96,7 @@ func (i *ExternalIDP) Reduce(event *models.Event) (err error) { return err } -func (i *ExternalIDP) processUser(event *models.Event) (err error) { +func (i *ExternalIDP) processUser(event *es_models.Event) (err error) { externalIDP := new(usr_view_model.ExternalIDPView) switch event.Type { case model.HumanExternalIDPAdded: @@ -68,19 +110,19 @@ func (i *ExternalIDP) processUser(event *models.Event) (err error) { if err != nil { return err } - return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event.Sequence, event.CreationDate) + return i.view.DeleteExternalIDP(externalIDP.ExternalUserID, externalIDP.IDPConfigID, event) case model.UserRemoved: - return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return i.view.DeleteExternalIDPsByUserID(event.AggregateID, event) default: - return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedExternalIDPSequence(event) } if err != nil { return err } - return i.view.PutExternalIDP(externalIDP, externalIDP.Sequence, event.CreationDate) + return i.view.PutExternalIDP(externalIDP, event) } -func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { +func (i *ExternalIDP) processIdpConfig(event *es_models.Event) (err error) { switch event.Type { case iam_es_model.IDPConfigChanged, org_es_model.IDPConfigChanged: configView := new(iam_view_model.IDPConfigView) @@ -105,9 +147,9 @@ func (i *ExternalIDP) processIdpConfig(event *models.Event) (err error) { for _, provider := range exterinalIDPs { i.fillConfigData(provider, config) } - return i.view.PutExternalIDPs(event.Sequence, event.CreationDate, exterinalIDPs...) + return i.view.PutExternalIDPs(event, exterinalIDPs...) default: - return i.view.ProcessedExternalIDPSequence(event.Sequence, event.CreationDate) + return i.view.ProcessedExternalIDPSequence(event) } return nil } @@ -128,7 +170,7 @@ func (i *ExternalIDP) fillConfigData(externalIDP *usr_view_model.ExternalIDPView externalIDP.IDPName = config.Name } -func (i *ExternalIDP) OnError(event *models.Event, err error) error { +func (i *ExternalIDP) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-4Rsu8", "id", event.AggregateID).WithError(err).Warn("something went wrong in idp provider handler") return spooler.HandleError(event, err, i.view.GetLatestExternalIDPFailedEvent, i.view.ProcessedExternalIDPFailedEvent, i.view.ProcessedExternalIDPSequence, i.errorCountUntilSkip) } diff --git a/internal/management/repository/eventsourcing/handler/user_grant.go b/internal/management/repository/eventsourcing/handler/user_grant.go index 0ffe6955ac..3c9f0a0f8f 100644 --- a/internal/management/repository/eventsourcing/handler/user_grant.go +++ b/internal/management/repository/eventsourcing/handler/user_grant.go @@ -3,7 +3,12 @@ package handler import ( "context" + "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" + "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" + "github.com/caos/zitadel/internal/eventstore/spooler" org_model "github.com/caos/zitadel/internal/org/model" org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing" proj_model "github.com/caos/zitadel/internal/project/model" @@ -13,42 +18,75 @@ import ( usr_events "github.com/caos/zitadel/internal/user/repository/eventsourcing" usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" grant_es_model "github.com/caos/zitadel/internal/usergrant/repository/eventsourcing/model" - - "github.com/caos/logging" - - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/eventstore/models" - "github.com/caos/zitadel/internal/eventstore/spooler" view_model "github.com/caos/zitadel/internal/usergrant/repository/view/model" ) -type UserGrant struct { - handler - eventstore eventstore.Eventstore - projectEvents *proj_event.ProjectEventstore - userEvents *usr_events.UserEventstore - orgEvents *org_events.OrgEventstore -} - const ( userGrantTable = "management.user_grants" ) +type UserGrant struct { + handler + projectEvents *proj_event.ProjectEventstore + userEvents *usr_events.UserEventstore + orgEvents *org_events.OrgEventstore + subscription *eventstore.Subscription +} + +func newUserGrant( + handler handler, + projectEvents *proj_event.ProjectEventstore, + userEvents *usr_events.UserEventstore, + orgEvents *org_events.OrgEventstore, +) *UserGrant { + h := &UserGrant{ + handler: handler, + projectEvents: projectEvents, + userEvents: userEvents, + orgEvents: orgEvents, + } + + h.subscribe() + + return h +} + +func (m *UserGrant) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} + func (u *UserGrant) ViewModel() string { return userGrantTable } -func (u *UserGrant) EventQuery() (*models.SearchQuery, error) { - sequence, err := u.view.GetLatestUserGrantSequence() +func (_ *UserGrant) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{grant_es_model.UserGrantAggregate, usr_es_model.UserAggregate, proj_es_model.ProjectAggregate} +} + +func (u *UserGrant) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := u.view.GetLatestUserGrantSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (u *UserGrant) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := u.view.GetLatestUserGrantSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(grant_es_model.UserGrantAggregate, usr_es_model.UserAggregate, proj_es_model.ProjectAggregate). + AggregateTypeFilter(u.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (u *UserGrant) Reduce(event *models.Event) (err error) { +func (u *UserGrant) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case grant_es_model.UserGrantAggregate: err = u.processUserGrant(event) @@ -60,7 +98,7 @@ func (u *UserGrant) Reduce(event *models.Event) (err error) { return err } -func (u *UserGrant) processUserGrant(event *models.Event) (err error) { +func (u *UserGrant) processUserGrant(event *es_models.Event) (err error) { grant := new(view_model.UserGrantView) switch event.Type { case grant_es_model.UserGrantAdded: @@ -79,17 +117,17 @@ func (u *UserGrant) processUserGrant(event *models.Event) (err error) { } err = grant.AppendEvent(event) case grant_es_model.UserGrantRemoved, grant_es_model.UserGrantCascadeRemoved: - return u.view.DeleteUserGrant(event.AggregateID, event.Sequence, event.CreationDate) + return u.view.DeleteUserGrant(event.AggregateID, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } if err != nil { return err } - return u.view.PutUserGrant(grant, grant.Sequence, event.CreationDate) + return u.view.PutUserGrant(grant, event) } -func (u *UserGrant) processUser(event *models.Event) (err error) { +func (u *UserGrant) processUser(event *es_models.Event) (err error) { switch event.Type { case usr_es_model.UserProfileChanged, usr_es_model.UserEmailChanged, @@ -101,7 +139,7 @@ func (u *UserGrant) processUser(event *models.Event) (err error) { return err } if len(grants) == 0 { - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } user, err := u.userEvents.UserByID(context.Background(), event.AggregateID) if err != nil { @@ -110,14 +148,14 @@ func (u *UserGrant) processUser(event *models.Event) (err error) { for _, grant := range grants { u.fillUserData(grant, user) } - return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate) + return u.view.PutUserGrants(grants, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } return nil } -func (u *UserGrant) processProject(event *models.Event) (err error) { +func (u *UserGrant) processProject(event *es_models.Event) (err error) { switch event.Type { case proj_es_model.ProjectChanged: grants, err := u.view.UserGrantsByProjectID(event.AggregateID) @@ -125,7 +163,7 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { return err } if len(grants) == 0 { - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } project, err := u.projectEvents.ProjectByID(context.Background(), event.AggregateID) if err != nil { @@ -134,9 +172,9 @@ func (u *UserGrant) processProject(event *models.Event) (err error) { for _, grant := range grants { u.fillProjectData(grant, project) } - return u.view.PutUserGrants(grants, event.Sequence, event.CreationDate) + return u.view.PutUserGrants(grants, event) default: - return u.view.ProcessedUserGrantSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedUserGrantSequence(event) } return nil } @@ -189,7 +227,7 @@ func (u *UserGrant) fillOrgData(grant *view_model.UserGrantView, org *org_model. } } -func (u *UserGrant) OnError(event *models.Event, err error) error { +func (u *UserGrant) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-8is4s", "id", event.AggregateID).WithError(err).Warn("something went wrong in user handler") return spooler.HandleError(event, err, u.view.GetLatestUserGrantFailedEvent, u.view.ProcessedUserGrantFailedEvent, u.view.ProcessedUserGrantSequence, u.errorCountUntilSkip) } diff --git a/internal/management/repository/eventsourcing/handler/user_membership.go b/internal/management/repository/eventsourcing/handler/user_membership.go index 8537905d47..e6a56fab90 100644 --- a/internal/management/repository/eventsourcing/handler/user_membership.go +++ b/internal/management/repository/eventsourcing/handler/user_membership.go @@ -2,48 +2,87 @@ package handler import ( "context" + + "github.com/caos/logging" + "github.com/caos/zitadel/internal/eventstore" + "github.com/caos/zitadel/internal/eventstore/models" + es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" + "github.com/caos/zitadel/internal/eventstore/spooler" iam_es_model "github.com/caos/zitadel/internal/iam/repository/eventsourcing/model" org_model "github.com/caos/zitadel/internal/org/model" org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing" + org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" proj_event "github.com/caos/zitadel/internal/project/repository/eventsourcing" proj_es_model "github.com/caos/zitadel/internal/project/repository/eventsourcing/model" - "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" - - "github.com/caos/logging" - - "github.com/caos/zitadel/internal/eventstore/models" - es_models "github.com/caos/zitadel/internal/eventstore/models" - "github.com/caos/zitadel/internal/eventstore/spooler" - org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" usr_model "github.com/caos/zitadel/internal/user/model" + "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" usr_es_model "github.com/caos/zitadel/internal/user/repository/view/model" ) +const ( + userMembershipTable = "management.user_memberships" +) + type UserMembership struct { handler orgEvents *org_event.OrgEventstore projectEvents *proj_event.ProjectEventstore + subscription *eventstore.Subscription } -const ( - userMembershipTable = "management.user_memberships" -) +func newUserMembership( + handler handler, + orgEvents *org_event.OrgEventstore, + projectEvents *proj_event.ProjectEventstore, +) *UserMembership { + h := &UserMembership{ + handler: handler, + orgEvents: orgEvents, + projectEvents: projectEvents, + } + + h.subscribe() + + return h +} + +func (m *UserMembership) subscribe() { + m.subscription = m.es.Subscribe(m.AggregateTypes()...) + go func() { + for event := range m.subscription.Events { + query.ReduceEvent(m, event) + } + }() +} func (m *UserMembership) ViewModel() string { return userMembershipTable } -func (m *UserMembership) EventQuery() (*models.SearchQuery, error) { - sequence, err := m.view.GetLatestUserMembershipSequence() +func (_ *UserMembership) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{iam_es_model.IAMAggregate, org_es_model.OrgAggregate, proj_es_model.ProjectAggregate, model.UserAggregate} +} + +func (u *UserMembership) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := u.view.GetLatestUserMembershipSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (m *UserMembership) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := m.view.GetLatestUserMembershipSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(iam_es_model.IAMAggregate, org_es_model.OrgAggregate, proj_es_model.ProjectAggregate, model.UserAggregate). + AggregateTypeFilter(m.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (m *UserMembership) Reduce(event *models.Event) (err error) { +func (m *UserMembership) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case iam_es_model.IAMAggregate: err = m.processIam(event) @@ -57,7 +96,7 @@ func (m *UserMembership) Reduce(event *models.Event) (err error) { return err } -func (m *UserMembership) processIam(event *models.Event) (err error) { +func (m *UserMembership) processIam(event *es_models.Event) (err error) { member := new(usr_es_model.UserMembershipView) err = member.AppendEvent(event) if err != nil { @@ -73,21 +112,21 @@ func (m *UserMembership) processIam(event *models.Event) (err error) { } err = member.AppendEvent(event) case iam_es_model.IAMMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeIam, event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedUserMembershipSequence(event) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) + return m.view.PutUserMembership(member, event) } func (m *UserMembership) fillIamDisplayName(member *usr_es_model.UserMembershipView) { member.DisplayName = member.AggregateID } -func (m *UserMembership) processOrg(event *models.Event) (err error) { +func (m *UserMembership) processOrg(event *es_models.Event) (err error) { member := new(usr_es_model.UserMembershipView) err = member.AppendEvent(event) if err != nil { @@ -103,16 +142,16 @@ func (m *UserMembership) processOrg(event *models.Event) (err error) { } err = member.AppendEvent(event) case org_es_model.OrgMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeOrganisation, event) case org_es_model.OrgChanged: return m.updateOrgDisplayName(event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedUserMembershipSequence(event) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) + return m.view.PutUserMembership(member, event) } func (m *UserMembership) fillOrgDisplayName(member *usr_es_model.UserMembershipView) (err error) { @@ -124,7 +163,7 @@ func (m *UserMembership) fillOrgDisplayName(member *usr_es_model.UserMembershipV return nil } -func (m *UserMembership) updateOrgDisplayName(event *models.Event) error { +func (m *UserMembership) updateOrgDisplayName(event *es_models.Event) error { org, err := m.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.AggregateID)) if err != nil { return err @@ -137,10 +176,10 @@ func (m *UserMembership) updateOrgDisplayName(event *models.Event) error { for _, membership := range memberships { membership.DisplayName = org.Name } - return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate) + return m.view.BulkPutUserMemberships(memberships, event) } -func (m *UserMembership) processProject(event *models.Event) (err error) { +func (m *UserMembership) processProject(event *es_models.Event) (err error) { member := new(usr_es_model.UserMembershipView) err = member.AppendEvent(event) if err != nil { @@ -156,7 +195,7 @@ func (m *UserMembership) processProject(event *models.Event) (err error) { } err = member.AppendEvent(event) case proj_es_model.ProjectMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, event.AggregateID, usr_model.MemberTypeProject, event) case proj_es_model.ProjectGrantMemberChanged: member, err = m.view.UserMembershipByIDs(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant) if err != nil { @@ -164,20 +203,20 @@ func (m *UserMembership) processProject(event *models.Event) (err error) { } err = member.AppendEvent(event) case proj_es_model.ProjectGrantMemberRemoved: - return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembership(member.UserID, event.AggregateID, member.ObjectID, usr_model.MemberTypeProjectGrant, event) case proj_es_model.ProjectChanged: return m.updateProjectDisplayName(event) case proj_es_model.ProjectRemoved: - return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembershipsByAggregateID(event.AggregateID, event) case proj_es_model.ProjectGrantRemoved: - return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembershipsByAggregateIDAndObjectID(event.AggregateID, member.ObjectID, event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedUserMembershipSequence(event) } if err != nil { return err } - return m.view.PutUserMembership(member, event.Sequence, event.CreationDate) + return m.view.PutUserMembership(member, event) } func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembershipView) (err error) { @@ -189,7 +228,7 @@ func (m *UserMembership) fillProjectDisplayName(member *usr_es_model.UserMembers return nil } -func (m *UserMembership) updateProjectDisplayName(event *models.Event) error { +func (m *UserMembership) updateProjectDisplayName(event *es_models.Event) error { project, err := m.projectEvents.ProjectByID(context.Background(), event.AggregateID) if err != nil { return err @@ -202,19 +241,19 @@ func (m *UserMembership) updateProjectDisplayName(event *models.Event) error { for _, membership := range memberships { membership.DisplayName = project.Name } - return m.view.BulkPutUserMemberships(memberships, event.Sequence, event.CreationDate) + return m.view.BulkPutUserMemberships(memberships, event) } -func (m *UserMembership) processUser(event *models.Event) (err error) { +func (m *UserMembership) processUser(event *es_models.Event) (err error) { switch event.Type { case model.UserRemoved: - return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event.Sequence, event.CreationDate) + return m.view.DeleteUserMembershipsByUserID(event.AggregateID, event) default: - return m.view.ProcessedUserMembershipSequence(event.Sequence, event.CreationDate) + return m.view.ProcessedUserMembershipSequence(event) } } -func (m *UserMembership) OnError(event *models.Event, err error) error { +func (m *UserMembership) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-Fwer2", "id", event.AggregateID).WithError(err).Warn("something went wrong in user membership handler") return spooler.HandleError(event, err, m.view.GetLatestUserMembershipFailedEvent, m.view.ProcessedUserMembershipFailedEvent, m.view.ProcessedUserMembershipSequence, m.errorCountUntilSkip) } diff --git a/internal/management/repository/eventsourcing/spooler/lock.go b/internal/management/repository/eventsourcing/spooler/lock.go index f24f98f6cc..9dd53a4cc3 100644 --- a/internal/management/repository/eventsourcing/spooler/lock.go +++ b/internal/management/repository/eventsourcing/spooler/lock.go @@ -2,7 +2,6 @@ package spooler import ( "database/sql" - es_locker "github.com/caos/zitadel/internal/eventstore/locker" "time" ) @@ -15,5 +14,5 @@ type locker struct { } func (l *locker) Renew(lockerID, viewModel string, waitTime time.Duration) error { - return es_locker.Renew(l.dbClient, lockTable, lockerID, viewModel, waitTime) + return nil } diff --git a/internal/management/repository/eventsourcing/view/application.go b/internal/management/repository/eventsourcing/view/application.go index 46672fc74a..eeb5c344e6 100644 --- a/internal/management/repository/eventsourcing/view/application.go +++ b/internal/management/repository/eventsourcing/view/application.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -24,40 +24,40 @@ func (v *View) SearchApplications(request *proj_model.ApplicationSearchRequest) return view.SearchApplications(v.Db, applicationTable, request) } -func (v *View) PutApplication(app *model.ApplicationView, eventTimestamp time.Time) error { +func (v *View) PutApplication(app *model.ApplicationView, event *models.Event) error { err := view.PutApplication(v.Db, applicationTable, app) if err != nil { return err } - return v.ProcessedApplicationSequence(app.Sequence, eventTimestamp) + return v.ProcessedApplicationSequence(event) } -func (v *View) PutApplications(apps []*model.ApplicationView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutApplications(apps []*model.ApplicationView, event *models.Event) error { err := view.PutApplications(v.Db, applicationTable, apps...) if err != nil { return err } - return v.ProcessedApplicationSequence(sequence, eventTimestamp) + return v.ProcessedApplicationSequence(event) } -func (v *View) DeleteApplication(appID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteApplication(appID string, event *models.Event) error { err := view.DeleteApplication(v.Db, applicationTable, appID) if err != nil { return nil } - return v.ProcessedApplicationSequence(eventSequence, eventTimestamp) + return v.ProcessedApplicationSequence(event) } func (v *View) DeleteApplicationsByProjectID(projectID string) error { return view.DeleteApplicationsByProjectID(v.Db, applicationTable, projectID) } -func (v *View) GetLatestApplicationSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(applicationTable) +func (v *View) GetLatestApplicationSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(applicationTable, aggregateType) } -func (v *View) ProcessedApplicationSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(applicationTable, eventSequence, eventTimestamp) +func (v *View) ProcessedApplicationSequence(event *models.Event) error { + return v.saveCurrentSequence(applicationTable, event) } func (v *View) UpdateApplicationSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/external_idps.go b/internal/management/repository/eventsourcing/view/external_idps.go index c2944c7a5f..0b8eb3648e 100644 --- a/internal/management/repository/eventsourcing/view/external_idps.go +++ b/internal/management/repository/eventsourcing/view/external_idps.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -33,43 +33,43 @@ func (v *View) SearchExternalIDPs(request *usr_model.ExternalIDPSearchRequest) ( return view.SearchExternalIDPs(v.Db, externalIDPTable, request) } -func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutExternalIDP(externalIDP *model.ExternalIDPView, event *models.Event) error { err := view.PutExternalIDP(v.Db, externalIDPTable, externalIDP) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) PutExternalIDPs(sequence uint64, eventTimestamp time.Time, externalIDPs ...*model.ExternalIDPView) error { +func (v *View) PutExternalIDPs(event *models.Event, externalIDPs ...*model.ExternalIDPView) error { err := view.PutExternalIDPs(v.Db, externalIDPTable, externalIDPs...) if err != nil { return err } - return v.ProcessedExternalIDPSequence(sequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteExternalIDP(externalUserID, idpConfigID string, event *models.Event) error { err := view.DeleteExternalIDP(v.Db, externalIDPTable, externalUserID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) DeleteExternalIDPsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteExternalIDPsByUserID(userID string, event *models.Event) error { err := view.DeleteExternalIDPsByUserID(v.Db, externalIDPTable, userID) if err != nil { return err } - return v.ProcessedExternalIDPSequence(eventSequence, eventTimestamp) + return v.ProcessedExternalIDPSequence(event) } -func (v *View) GetLatestExternalIDPSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(externalIDPTable) +func (v *View) GetLatestExternalIDPSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(externalIDPTable, aggregateType) } -func (v *View) ProcessedExternalIDPSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(externalIDPTable, eventSequence, eventTimestamp) +func (v *View) ProcessedExternalIDPSequence(event *models.Event) error { + return v.saveCurrentSequence(externalIDPTable, event) } func (v *View) UpdateExternalIDPSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/idp_configs.go b/internal/management/repository/eventsourcing/view/idp_configs.go index a9dfde45da..5770f36b38 100644 --- a/internal/management/repository/eventsourcing/view/idp_configs.go +++ b/internal/management/repository/eventsourcing/view/idp_configs.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/view" iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -21,28 +21,28 @@ func (v *View) SearchIDPConfigs(request *iam_model.IDPConfigSearchRequest) ([]*i return view.SearchIDPs(v.Db, idpConfigTable, request) } -func (v *View) PutIDPConfig(idp *iam_es_model.IDPConfigView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutIDPConfig(idp *iam_es_model.IDPConfigView, event *models.Event) error { err := view.PutIDP(v.Db, idpConfigTable, idp) if err != nil { return err } - return v.ProcessedIDPConfigSequence(sequence, eventTimestamp) + return v.ProcessedIDPConfigSequence(event) } -func (v *View) DeleteIDPConfig(idpID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIDPConfig(idpID string, event *models.Event) error { err := view.DeleteIDP(v.Db, idpConfigTable, idpID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPConfigSequence(eventSequence, eventTimestamp) + return v.ProcessedIDPConfigSequence(event) } -func (v *View) GetLatestIDPConfigSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(idpConfigTable) +func (v *View) GetLatestIDPConfigSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(idpConfigTable, aggregateType) } -func (v *View) ProcessedIDPConfigSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(idpConfigTable, eventSequence, eventTimestamp) +func (v *View) ProcessedIDPConfigSequence(event *models.Event) error { + return v.saveCurrentSequence(idpConfigTable, event) } func (v *View) UpdateIDPConfigSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/idp_providers.go b/internal/management/repository/eventsourcing/view/idp_providers.go index 207feb621f..a293ec1637 100644 --- a/internal/management/repository/eventsourcing/view/idp_providers.go +++ b/internal/management/repository/eventsourcing/view/idp_providers.go @@ -2,11 +2,11 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" iam_model "github.com/caos/zitadel/internal/iam/model" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -25,44 +25,44 @@ func (v *View) SearchIDPProviders(request *iam_model.IDPProviderSearchRequest) ( return view.SearchIDPProviders(v.Db, idpProviderTable, request) } -func (v *View) PutIDPProvider(provider *model.IDPProviderView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutIDPProvider(provider *model.IDPProviderView, event *models.Event) error { err := view.PutIDPProvider(v.Db, idpProviderTable, provider) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) PutIDPProviders(sequence uint64, eventTimestamp time.Time, providers ...*model.IDPProviderView) error { +func (v *View) PutIDPProviders(event *models.Event, providers ...*model.IDPProviderView) error { err := view.PutIDPProviders(v.Db, idpProviderTable, providers...) if err != nil { return err } - return v.ProcessedIDPProviderSequence(sequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIDPProvider(aggregateID, idpConfigID string, event *models.Event) error { err := view.DeleteIDPProvider(v.Db, idpProviderTable, aggregateID, idpConfigID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) DeleteIDPProvidersByAggregateID(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteIDPProvidersByAggregateID(aggregateID string, event *models.Event) error { err := view.DeleteIDPProvidersByAggregateID(v.Db, idpProviderTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedIDPProviderSequence(eventSequence, eventTimestamp) + return v.ProcessedIDPProviderSequence(event) } -func (v *View) GetLatestIDPProviderSequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(idpProviderTable) +func (v *View) GetLatestIDPProviderSequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(idpProviderTable, aggregateType) } -func (v *View) ProcessedIDPProviderSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(idpProviderTable, eventSequence, eventTimestamp) +func (v *View) ProcessedIDPProviderSequence(event *models.Event) error { + return v.saveCurrentSequence(idpProviderTable, event) } func (v *View) UpdateIDPProviderSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/label_policies.go b/internal/management/repository/eventsourcing/view/label_policies.go index 27b234fc29..05bb9550a4 100644 --- a/internal/management/repository/eventsourcing/view/label_policies.go +++ b/internal/management/repository/eventsourcing/view/label_policies.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) LabelPolicyByAggregateID(aggregateID string) (*model.LabelPolicyV return view.GetLabelPolicyByAggregateID(v.Db, labelPolicyTable, aggregateID) } -func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutLabelPolicy(policy *model.LabelPolicyView, event *models.Event) error { err := view.PutLabelPolicy(v.Db, labelPolicyTable, policy) if err != nil { return err } - return v.ProcessedLabelPolicySequence(sequence, eventTimestamp) + return v.ProcessedLabelPolicySequence(event) } -func (v *View) DeleteLabelPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteLabelPolicy(aggregateID string, event *models.Event) error { err := view.DeleteLabelPolicy(v.Db, labelPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedLabelPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedLabelPolicySequence(event) } -func (v *View) GetLatestLabelPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(labelPolicyTable) +func (v *View) GetLatestLabelPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(labelPolicyTable, aggregateType) } -func (v *View) ProcessedLabelPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(labelPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedLabelPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(labelPolicyTable, event) } func (v *View) UpdateLabelPolicySpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/login_policies.go b/internal/management/repository/eventsourcing/view/login_policies.go index c37f4283d6..56e6e80f8f 100644 --- a/internal/management/repository/eventsourcing/view/login_policies.go +++ b/internal/management/repository/eventsourcing/view/login_policies.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) LoginPolicyByAggregateID(aggregateID string) (*model.LoginPolicyV return view.GetLoginPolicyByAggregateID(v.Db, loginPolicyTable, aggregateID) } -func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutLoginPolicy(policy *model.LoginPolicyView, event *models.Event) error { err := view.PutLoginPolicy(v.Db, loginPolicyTable, policy) if err != nil { return err } - return v.ProcessedLoginPolicySequence(sequence, eventTimestamp) + return v.ProcessedLoginPolicySequence(event) } -func (v *View) DeleteLoginPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteLoginPolicy(aggregateID string, event *models.Event) error { err := view.DeleteLoginPolicy(v.Db, loginPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedLoginPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedLoginPolicySequence(event) } -func (v *View) GetLatestLoginPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(loginPolicyTable) +func (v *View) GetLatestLoginPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(loginPolicyTable, aggregateType) } -func (v *View) ProcessedLoginPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(loginPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedLoginPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(loginPolicyTable, event) } func (v *View) UpdateLoginPolicySpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/machine_keys.go b/internal/management/repository/eventsourcing/view/machine_keys.go index b037137c82..da50ed6760 100644 --- a/internal/management/repository/eventsourcing/view/machine_keys.go +++ b/internal/management/repository/eventsourcing/view/machine_keys.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -24,39 +24,39 @@ func (v *View) SearchMachineKeys(request *usr_model.MachineKeySearchRequest) ([] return view.SearchMachineKeys(v.Db, machineKeyTable, request) } -func (v *View) PutMachineKey(org *model.MachineKeyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutMachineKey(org *model.MachineKeyView, event *models.Event) error { err := view.PutMachineKey(v.Db, machineKeyTable, org) if err != nil { return err } - if sequence != 0 { - return v.ProcessedMachineKeySequence(sequence, eventTimestamp) + if event.Sequence != 0 { + return v.ProcessedMachineKeySequence(event) } return nil } -func (v *View) DeleteMachineKey(keyID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteMachineKey(keyID string, event *models.Event) error { err := view.DeleteMachineKey(v.Db, machineKeyTable, keyID) if err != nil { return nil } - return v.ProcessedMachineKeySequence(eventSequence, eventTimestamp) + return v.ProcessedMachineKeySequence(event) } -func (v *View) DeleteMachineKeysByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteMachineKeysByUserID(userID string, event *models.Event) error { err := view.DeleteMachineKey(v.Db, machineKeyTable, userID) if err != nil { return nil } - return v.ProcessedMachineKeySequence(eventSequence, eventTimestamp) + return v.ProcessedMachineKeySequence(event) } -func (v *View) GetLatestMachineKeySequence() (*repository.CurrentSequence, error) { - return v.latestSequence(machineKeyTable) +func (v *View) GetLatestMachineKeySequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(machineKeyTable, aggregateType) } -func (v *View) ProcessedMachineKeySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(machineKeyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedMachineKeySequence(event *models.Event) error { + return v.saveCurrentSequence(machineKeyTable, event) } func (v *View) UpdateMachineKeySpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/org.go b/internal/management/repository/eventsourcing/view/org.go index a5de5fdb46..3a53b92031 100644 --- a/internal/management/repository/eventsourcing/view/org.go +++ b/internal/management/repository/eventsourcing/view/org.go @@ -1,10 +1,10 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" org_view "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -15,12 +15,12 @@ func (v *View) OrgByID(orgID string) (*model.OrgView, error) { return org_view.OrgByID(v.Db, orgTable, orgID) } -func (v *View) PutOrg(org *model.OrgView, eventTimestamp time.Time) error { +func (v *View) PutOrg(org *model.OrgView, event *models.Event) error { err := org_view.PutOrg(v.Db, orgTable, org) if err != nil { return err } - return v.ProcessedOrgSequence(org.Sequence, eventTimestamp) + return v.ProcessedOrgSequence(event) } func (v *View) GetLatestOrgFailedEvent(sequence uint64) (*repository.FailedEvent, error) { @@ -35,10 +35,10 @@ func (v *View) UpdateOrgSpoolerRunTimestamp() error { return v.updateSpoolerRunSequence(orgTable) } -func (v *View) GetLatestOrgSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(orgTable) +func (v *View) GetLatestOrgSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(orgTable, aggregateType) } -func (v *View) ProcessedOrgSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgSequence(event *models.Event) error { + return v.saveCurrentSequence(orgTable, event) } diff --git a/internal/management/repository/eventsourcing/view/org_domain.go b/internal/management/repository/eventsourcing/view/org_domain.go index 94f3f84c95..f8103674aa 100644 --- a/internal/management/repository/eventsourcing/view/org_domain.go +++ b/internal/management/repository/eventsourcing/view/org_domain.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" org_model "github.com/caos/zitadel/internal/org/model" "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -28,39 +28,39 @@ func (v *View) SearchOrgDomains(request *org_model.OrgDomainSearchRequest) ([]*m return view.SearchOrgDomains(v.Db, orgDomainTable, request) } -func (v *View) PutOrgDomain(org *model.OrgDomainView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutOrgDomain(org *model.OrgDomainView, event *models.Event) error { err := view.PutOrgDomain(v.Db, orgDomainTable, org) if err != nil { return err } - if sequence != 0 { - return v.ProcessedOrgDomainSequence(sequence, eventTimestamp) + if event.Sequence != 0 { + return v.ProcessedOrgDomainSequence(event) } return nil } -func (v *View) PutOrgDomains(domains []*model.OrgDomainView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutOrgDomains(domains []*model.OrgDomainView, event *models.Event) error { err := view.PutOrgDomains(v.Db, orgDomainTable, domains...) if err != nil { return err } - return v.ProcessedUserSequence(sequence, eventTimestamp) + return v.ProcessedUserSequence(event) } -func (v *View) DeleteOrgDomain(orgID, domain string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteOrgDomain(orgID, domain string, event *models.Event) error { err := view.DeleteOrgDomain(v.Db, orgDomainTable, orgID, domain) if err != nil { return nil } - return v.ProcessedOrgDomainSequence(eventSequence, eventTimestamp) + return v.ProcessedOrgDomainSequence(event) } -func (v *View) GetLatestOrgDomainSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(orgDomainTable) +func (v *View) GetLatestOrgDomainSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(orgDomainTable, aggregateType) } -func (v *View) ProcessedOrgDomainSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgDomainTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgDomainSequence(event *models.Event) error { + return v.saveCurrentSequence(orgDomainTable, event) } func (v *View) UpdateOrgDomainSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/org_iam_policy.go b/internal/management/repository/eventsourcing/view/org_iam_policy.go index db9d113155..90d3de2b9c 100644 --- a/internal/management/repository/eventsourcing/view/org_iam_policy.go +++ b/internal/management/repository/eventsourcing/view/org_iam_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) OrgIAMPolicyByAggregateID(aggregateID string) (*model.OrgIAMPolic return view.GetOrgIAMPolicyByAggregateID(v.Db, orgIAMPolicyTable, aggregateID) } -func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutOrgIAMPolicy(policy *model.OrgIAMPolicyView, event *models.Event) error { err := view.PutOrgIAMPolicy(v.Db, orgIAMPolicyTable, policy) if err != nil { return err } - return v.ProcessedOrgIAMPolicySequence(sequence, eventTimestamp) + return v.ProcessedOrgIAMPolicySequence(event) } -func (v *View) DeleteOrgIAMPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteOrgIAMPolicy(aggregateID string, event *models.Event) error { err := view.DeleteOrgIAMPolicy(v.Db, orgIAMPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedOrgIAMPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedOrgIAMPolicySequence(event) } -func (v *View) GetLatestOrgIAMPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(orgIAMPolicyTable) +func (v *View) GetLatestOrgIAMPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(orgIAMPolicyTable, aggregateType) } -func (v *View) ProcessedOrgIAMPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgIAMPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgIAMPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(orgIAMPolicyTable, event) } func (v *View) UpdateOrgIAMPolicySpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/org_member.go b/internal/management/repository/eventsourcing/view/org_member.go index d1cb20b3c0..2ea8f79c90 100644 --- a/internal/management/repository/eventsourcing/view/org_member.go +++ b/internal/management/repository/eventsourcing/view/org_member.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" org_model "github.com/caos/zitadel/internal/org/model" "github.com/caos/zitadel/internal/org/repository/view" "github.com/caos/zitadel/internal/org/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -24,44 +24,44 @@ func (v *View) OrgMembersByUserID(userID string) ([]*model.OrgMemberView, error) return view.OrgMembersByUserID(v.Db, orgMemberTable, userID) } -func (v *View) PutOrgMember(member *model.OrgMemberView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutOrgMember(member *model.OrgMemberView, event *models.Event) error { err := view.PutOrgMember(v.Db, orgMemberTable, member) if err != nil { return err } - return v.ProcessedOrgMemberSequence(sequence, eventTimestamp) + return v.ProcessedOrgMemberSequence(event) } -func (v *View) PutOrgMembers(members []*model.OrgMemberView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutOrgMembers(members []*model.OrgMemberView, event *models.Event) error { err := view.PutOrgMembers(v.Db, orgMemberTable, members...) if err != nil { return err } - return v.ProcessedOrgMemberSequence(sequence, eventTimestamp) + return v.ProcessedOrgMemberSequence(event) } -func (v *View) DeleteOrgMember(orgID, userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteOrgMember(orgID, userID string, event *models.Event) error { err := view.DeleteOrgMember(v.Db, orgMemberTable, orgID, userID) if err != nil { return nil } - return v.ProcessedOrgMemberSequence(eventSequence, eventTimestamp) + return v.ProcessedOrgMemberSequence(event) } -func (v *View) DeleteOrgMembersByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteOrgMembersByUserID(userID string, event *models.Event) error { err := view.DeleteOrgMembersByUserID(v.Db, orgMemberTable, userID) if err != nil { return nil } - return v.ProcessedOrgMemberSequence(eventSequence, eventTimestamp) + return v.ProcessedOrgMemberSequence(event) } -func (v *View) GetLatestOrgMemberSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(orgMemberTable) +func (v *View) GetLatestOrgMemberSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(orgMemberTable, aggregateType) } -func (v *View) ProcessedOrgMemberSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(orgMemberTable, eventSequence, eventTimestamp) +func (v *View) ProcessedOrgMemberSequence(event *models.Event) error { + return v.saveCurrentSequence(orgMemberTable, event) } func (v *View) UpdateOrgMemberSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/password_age_policy.go b/internal/management/repository/eventsourcing/view/password_age_policy.go index e37d650072..e1bd56a596 100644 --- a/internal/management/repository/eventsourcing/view/password_age_policy.go +++ b/internal/management/repository/eventsourcing/view/password_age_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) PasswordAgePolicyByAggregateID(aggregateID string) (*model.Passwo return view.GetPasswordAgePolicyByAggregateID(v.Db, passwordAgePolicyTable, aggregateID) } -func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutPasswordAgePolicy(policy *model.PasswordAgePolicyView, event *models.Event) error { err := view.PutPasswordAgePolicy(v.Db, passwordAgePolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordAgePolicySequence(sequence, eventTimestamp) + return v.ProcessedPasswordAgePolicySequence(event) } -func (v *View) DeletePasswordAgePolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeletePasswordAgePolicy(aggregateID string, event *models.Event) error { err := view.DeletePasswordAgePolicy(v.Db, passwordAgePolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordAgePolicySequence(eventSequence, eventTimestamp) + return v.ProcessedPasswordAgePolicySequence(event) } -func (v *View) GetLatestPasswordAgePolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(passwordAgePolicyTable) +func (v *View) GetLatestPasswordAgePolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(passwordAgePolicyTable, aggregateType) } -func (v *View) ProcessedPasswordAgePolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(passwordAgePolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedPasswordAgePolicySequence(event *models.Event) error { + return v.saveCurrentSequence(passwordAgePolicyTable, event) } func (v *View) UpdatePasswordAgePolicySpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/password_complexity_policy.go b/internal/management/repository/eventsourcing/view/password_complexity_policy.go index 70895d13a9..80d9e2d90d 100644 --- a/internal/management/repository/eventsourcing/view/password_complexity_policy.go +++ b/internal/management/repository/eventsourcing/view/password_complexity_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) PasswordComplexityPolicyByAggregateID(aggregateID string) (*model return view.GetPasswordComplexityPolicyByAggregateID(v.Db, passwordComplexityPolicyTable, aggregateID) } -func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutPasswordComplexityPolicy(policy *model.PasswordComplexityPolicyView, event *models.Event) error { err := view.PutPasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordComplexityPolicySequence(sequence, eventTimestamp) + return v.ProcessedPasswordComplexityPolicySequence(event) } -func (v *View) DeletePasswordComplexityPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeletePasswordComplexityPolicy(aggregateID string, event *models.Event) error { err := view.DeletePasswordComplexityPolicy(v.Db, passwordComplexityPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordComplexityPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedPasswordComplexityPolicySequence(event) } -func (v *View) GetLatestPasswordComplexityPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(passwordComplexityPolicyTable) +func (v *View) GetLatestPasswordComplexityPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(passwordComplexityPolicyTable, aggregateType) } -func (v *View) ProcessedPasswordComplexityPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(passwordComplexityPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedPasswordComplexityPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(passwordComplexityPolicyTable, event) } func (v *View) UpdatePasswordComplexityPolicySpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/password_lockout_policy.go b/internal/management/repository/eventsourcing/view/password_lockout_policy.go index 11e3955720..549f704c75 100644 --- a/internal/management/repository/eventsourcing/view/password_lockout_policy.go +++ b/internal/management/repository/eventsourcing/view/password_lockout_policy.go @@ -2,10 +2,10 @@ package view import ( "github.com/caos/zitadel/internal/errors" + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/iam/repository/view" "github.com/caos/zitadel/internal/iam/repository/view/model" global_view "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -16,28 +16,28 @@ func (v *View) PasswordLockoutPolicyByAggregateID(aggregateID string) (*model.Pa return view.GetPasswordLockoutPolicyByAggregateID(v.Db, passwordLockoutPolicyTable, aggregateID) } -func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutPasswordLockoutPolicy(policy *model.PasswordLockoutPolicyView, event *models.Event) error { err := view.PutPasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, policy) if err != nil { return err } - return v.ProcessedPasswordLockoutPolicySequence(sequence, eventTimestamp) + return v.ProcessedPasswordLockoutPolicySequence(event) } -func (v *View) DeletePasswordLockoutPolicy(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeletePasswordLockoutPolicy(aggregateID string, event *models.Event) error { err := view.DeletePasswordLockoutPolicy(v.Db, passwordLockoutPolicyTable, aggregateID) if err != nil && !errors.IsNotFound(err) { return err } - return v.ProcessedPasswordLockoutPolicySequence(eventSequence, eventTimestamp) + return v.ProcessedPasswordLockoutPolicySequence(event) } -func (v *View) GetLatestPasswordLockoutPolicySequence() (*global_view.CurrentSequence, error) { - return v.latestSequence(passwordLockoutPolicyTable) +func (v *View) GetLatestPasswordLockoutPolicySequence(aggregateType string) (*global_view.CurrentSequence, error) { + return v.latestSequence(passwordLockoutPolicyTable, aggregateType) } -func (v *View) ProcessedPasswordLockoutPolicySequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(passwordLockoutPolicyTable, eventSequence, eventTimestamp) +func (v *View) ProcessedPasswordLockoutPolicySequence(event *models.Event) error { + return v.saveCurrentSequence(passwordLockoutPolicyTable, event) } func (v *View) UpdatePasswordLockoutPolicySpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/project.go b/internal/management/repository/eventsourcing/view/project.go index fede8830ee..8676b0ed2c 100644 --- a/internal/management/repository/eventsourcing/view/project.go +++ b/internal/management/repository/eventsourcing/view/project.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -20,28 +20,28 @@ func (v *View) SearchProjects(request *proj_model.ProjectViewSearchRequest) ([]* return view.SearchProjects(v.Db, projectTable, request) } -func (v *View) PutProject(project *model.ProjectView, eventTimestamp time.Time) error { +func (v *View) PutProject(project *model.ProjectView, event *models.Event) error { err := view.PutProject(v.Db, projectTable, project) if err != nil { return err } - return v.ProcessedProjectSequence(project.Sequence, eventTimestamp) + return v.ProcessedProjectSequence(event) } -func (v *View) DeleteProject(projectID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteProject(projectID string, event *models.Event) error { err := view.DeleteProject(v.Db, projectTable, projectID) if err != nil { return nil } - return v.ProcessedProjectSequence(eventSequence, eventTimestamp) + return v.ProcessedProjectSequence(event) } -func (v *View) GetLatestProjectSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(projectTable) +func (v *View) GetLatestProjectSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(projectTable, aggregateType) } -func (v *View) ProcessedProjectSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(projectTable, eventSequence, eventTimestamp) +func (v *View) ProcessedProjectSequence(event *models.Event) error { + return v.saveCurrentSequence(projectTable, event) } func (v *View) UpdateProjectSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/project_grant.go b/internal/management/repository/eventsourcing/view/project_grant.go index 64f1f6272e..ab54927a30 100644 --- a/internal/management/repository/eventsourcing/view/project_grant.go +++ b/internal/management/repository/eventsourcing/view/project_grant.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -32,40 +32,40 @@ func (v *View) SearchProjectGrants(request *proj_model.ProjectGrantViewSearchReq return view.SearchProjectGrants(v.Db, grantedProjectTable, request) } -func (v *View) PutProjectGrant(grant *model.ProjectGrantView, eventTimestamp time.Time) error { +func (v *View) PutProjectGrant(grant *model.ProjectGrantView, event *models.Event) error { err := view.PutProjectGrant(v.Db, grantedProjectTable, grant) if err != nil { return err } - return v.ProcessedProjectGrantSequence(grant.Sequence, eventTimestamp) + return v.ProcessedProjectGrantSequence(event) } -func (v *View) PutProjectGrants(grants []*model.ProjectGrantView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutProjectGrants(grants []*model.ProjectGrantView, event *models.Event) error { err := view.PutProjectGrants(v.Db, grantedProjectTable, grants...) if err != nil { return err } - return v.ProcessedProjectGrantSequence(sequence, eventTimestamp) + return v.ProcessedProjectGrantSequence(event) } -func (v *View) DeleteProjectGrant(grantID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteProjectGrant(grantID string, event *models.Event) error { err := view.DeleteProjectGrant(v.Db, grantedProjectTable, grantID) if err != nil { return err } - return v.ProcessedProjectGrantSequence(eventSequence, eventTimestamp) + return v.ProcessedProjectGrantSequence(event) } func (v *View) DeleteProjectGrantsByProjectID(projectID string) error { return view.DeleteProjectGrantsByProjectID(v.Db, grantedProjectTable, projectID) } -func (v *View) GetLatestProjectGrantSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(grantedProjectTable) +func (v *View) GetLatestProjectGrantSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(grantedProjectTable, aggregateType) } -func (v *View) ProcessedProjectGrantSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(grantedProjectTable, eventSequence, eventTimestamp) +func (v *View) ProcessedProjectGrantSequence(event *models.Event) error { + return v.saveCurrentSequence(grantedProjectTable, event) } func (v *View) UpdateProjectGrantSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/project_grant_member.go b/internal/management/repository/eventsourcing/view/project_grant_member.go index b9cf4391ba..83ae463190 100644 --- a/internal/management/repository/eventsourcing/view/project_grant_member.go +++ b/internal/management/repository/eventsourcing/view/project_grant_member.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -28,40 +28,40 @@ func (v *View) ProjectGrantMembersByUserID(userID string) ([]*model.ProjectGrant return view.ProjectGrantMembersByUserID(v.Db, projectGrantMemberTable, userID) } -func (v *View) PutProjectGrantMember(member *model.ProjectGrantMemberView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutProjectGrantMember(member *model.ProjectGrantMemberView, event *models.Event) error { err := view.PutProjectGrantMember(v.Db, projectGrantMemberTable, member) if err != nil { return err } - return v.ProcessedProjectGrantMemberSequence(sequence, eventTimestamp) + return v.ProcessedProjectGrantMemberSequence(event) } -func (v *View) PutProjectGrantMembers(members []*model.ProjectGrantMemberView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutProjectGrantMembers(members []*model.ProjectGrantMemberView, event *models.Event) error { err := view.PutProjectGrantMembers(v.Db, projectGrantMemberTable, members...) if err != nil { return err } - return v.ProcessedProjectGrantMemberSequence(sequence, eventTimestamp) + return v.ProcessedProjectGrantMemberSequence(event) } -func (v *View) DeleteProjectGrantMember(grantID, userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteProjectGrantMember(grantID, userID string, event *models.Event) error { err := view.DeleteProjectGrantMember(v.Db, projectGrantMemberTable, grantID, userID) if err != nil { return nil } - return v.ProcessedProjectGrantMemberSequence(eventSequence, eventTimestamp) + return v.ProcessedProjectGrantMemberSequence(event) } func (v *View) DeleteProjectGrantMembersByProjectID(projectID string) error { return view.DeleteProjectGrantMembersByProjectID(v.Db, projectGrantMemberTable, projectID) } -func (v *View) GetLatestProjectGrantMemberSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(projectGrantMemberTable) +func (v *View) GetLatestProjectGrantMemberSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(projectGrantMemberTable, aggregateType) } -func (v *View) ProcessedProjectGrantMemberSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(projectGrantMemberTable, eventSequence, eventTimestamp) +func (v *View) ProcessedProjectGrantMemberSequence(event *models.Event) error { + return v.saveCurrentSequence(projectGrantMemberTable, event) } func (v *View) UpdateProjectGrantMemberSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/project_member.go b/internal/management/repository/eventsourcing/view/project_member.go index c21dee73e2..a867916939 100644 --- a/internal/management/repository/eventsourcing/view/project_member.go +++ b/internal/management/repository/eventsourcing/view/project_member.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -28,40 +28,40 @@ func (v *View) ProjectMembersByUserID(userID string) ([]*model.ProjectMemberView return view.ProjectMembersByUserID(v.Db, projectMemberTable, userID) } -func (v *View) PutProjectMember(project *model.ProjectMemberView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutProjectMember(project *model.ProjectMemberView, event *models.Event) error { err := view.PutProjectMember(v.Db, projectMemberTable, project) if err != nil { return err } - return v.ProcessedProjectMemberSequence(sequence, eventTimestamp) + return v.ProcessedProjectMemberSequence(event) } -func (v *View) PutProjectMembers(project []*model.ProjectMemberView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutProjectMembers(project []*model.ProjectMemberView, event *models.Event) error { err := view.PutProjectMembers(v.Db, projectMemberTable, project...) if err != nil { return err } - return v.ProcessedProjectMemberSequence(sequence, eventTimestamp) + return v.ProcessedProjectMemberSequence(event) } -func (v *View) DeleteProjectMember(projectID, userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteProjectMember(projectID, userID string, event *models.Event) error { err := view.DeleteProjectMember(v.Db, projectMemberTable, projectID, userID) if err != nil { return nil } - return v.ProcessedProjectMemberSequence(eventSequence, eventTimestamp) + return v.ProcessedProjectMemberSequence(event) } func (v *View) DeleteProjectMembersByProjectID(projectID string) error { return view.DeleteProjectMembersByProjectID(v.Db, projectMemberTable, projectID) } -func (v *View) GetLatestProjectMemberSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(projectMemberTable) +func (v *View) GetLatestProjectMemberSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(projectMemberTable, aggregateType) } -func (v *View) ProcessedProjectMemberSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(projectMemberTable, eventSequence, eventTimestamp) +func (v *View) ProcessedProjectMemberSequence(event *models.Event) error { + return v.saveCurrentSequence(projectMemberTable, event) } func (v *View) UpdateProjectMemberSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/project_role.go b/internal/management/repository/eventsourcing/view/project_role.go index 6703a93efd..df56939309 100644 --- a/internal/management/repository/eventsourcing/view/project_role.go +++ b/internal/management/repository/eventsourcing/view/project_role.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" proj_model "github.com/caos/zitadel/internal/project/model" "github.com/caos/zitadel/internal/project/repository/view" "github.com/caos/zitadel/internal/project/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -32,32 +32,32 @@ func (v *View) SearchProjectRoles(request *proj_model.ProjectRoleSearchRequest) return view.SearchProjectRoles(v.Db, projectRoleTable, request) } -func (v *View) PutProjectRole(project *model.ProjectRoleView, eventTimestamp time.Time) error { +func (v *View) PutProjectRole(project *model.ProjectRoleView, event *models.Event) error { err := view.PutProjectRole(v.Db, projectRoleTable, project) if err != nil { return err } - return v.ProcessedProjectRoleSequence(project.Sequence, eventTimestamp) + return v.ProcessedProjectRoleSequence(event) } -func (v *View) DeleteProjectRole(projectID, orgID, key string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteProjectRole(projectID, orgID, key string, event *models.Event) error { err := view.DeleteProjectRole(v.Db, projectRoleTable, projectID, orgID, key) if err != nil { return nil } - return v.ProcessedProjectRoleSequence(eventSequence, eventTimestamp) + return v.ProcessedProjectRoleSequence(event) } func (v *View) DeleteProjectRolesByProjectID(projectID string) error { return view.DeleteProjectRolesByProjectID(v.Db, projectRoleTable, projectID) } -func (v *View) GetLatestProjectRoleSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(projectRoleTable) +func (v *View) GetLatestProjectRoleSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(projectRoleTable, aggregateType) } -func (v *View) ProcessedProjectRoleSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(projectRoleTable, eventSequence, eventTimestamp) +func (v *View) ProcessedProjectRoleSequence(event *models.Event) error { + return v.saveCurrentSequence(projectRoleTable, event) } func (v *View) UpdateProjectRoleSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/sequence.go b/internal/management/repository/eventsourcing/view/sequence.go index 82354c98e4..808ff58216 100644 --- a/internal/management/repository/eventsourcing/view/sequence.go +++ b/internal/management/repository/eventsourcing/view/sequence.go @@ -1,24 +1,26 @@ package view import ( - "github.com/caos/zitadel/internal/view/repository" "time" + + "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/view/repository" ) const ( sequencesTable = "management.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimestamp time.Time) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimestamp) +func (v *View) saveCurrentSequence(viewName string, event *models.Event) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, string(event.AggregateType), event.Sequence, event.CreationDate) } -func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { - return repository.LatestSequence(v.Db, sequencesTable, viewName) +func (v *View) latestSequence(viewName, aggregateType string) (*repository.CurrentSequence, error) { + return repository.LatestSequence(v.Db, sequencesTable, viewName, aggregateType) } func (v *View) updateSpoolerRunSequence(viewName string) error { - currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName, "") if err != nil { return err } @@ -26,5 +28,8 @@ func (v *View) updateSpoolerRunSequence(viewName string) error { currentSequence.ViewName = viewName } currentSequence.LastSuccessfulSpoolerRun = time.Now() + //update all aggregate types + //TODO: not sure if all scenarios work as expected + currentSequence.AggregateType = "" return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) } diff --git a/internal/management/repository/eventsourcing/view/user.go b/internal/management/repository/eventsourcing/view/user.go index 69fc14a270..cd7b2a4744 100644 --- a/internal/management/repository/eventsourcing/view/user.go +++ b/internal/management/repository/eventsourcing/view/user.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -40,39 +40,39 @@ func (v *View) UserMFAs(userID string) ([]*usr_model.MultiFactor, error) { return view.UserMFAs(v.Db, userTable, userID) } -func (v *View) PutUsers(user []*model.UserView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUsers(user []*model.UserView, event *models.Event) error { err := view.PutUsers(v.Db, userTable, user...) if err != nil { return err } - return v.ProcessedUserSequence(sequence, eventTimestamp) + return v.ProcessedUserSequence(event) } -func (v *View) PutUser(user *model.UserView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUser(user *model.UserView, event *models.Event) error { err := view.PutUser(v.Db, userTable, user) if err != nil { return err } - if sequence != 0 { - return v.ProcessedUserSequence(sequence, eventTimestamp) + if event.Sequence != 0 { + return v.ProcessedUserSequence(event) } return nil } -func (v *View) DeleteUser(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUser(userID string, event *models.Event) error { err := view.DeleteUser(v.Db, userTable, userID) if err != nil { return nil } - return v.ProcessedUserSequence(eventSequence, eventTimestamp) + return v.ProcessedUserSequence(event) } -func (v *View) GetLatestUserSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userTable) +func (v *View) GetLatestUserSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userTable, aggregateType) } -func (v *View) ProcessedUserSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserSequence(event *models.Event) error { + return v.saveCurrentSequence(userTable, event) } func (v *View) UpdateUserSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/user_grant.go b/internal/management/repository/eventsourcing/view/user_grant.go index 209fbfe6f4..5f20eaa0f2 100644 --- a/internal/management/repository/eventsourcing/view/user_grant.go +++ b/internal/management/repository/eventsourcing/view/user_grant.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" grant_model "github.com/caos/zitadel/internal/usergrant/model" "github.com/caos/zitadel/internal/usergrant/repository/view" "github.com/caos/zitadel/internal/usergrant/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -40,36 +40,36 @@ func (v *View) UserGrantsByOrgIDAndProjectID(orgID, projectID string) ([]*model. return view.UserGrantsByOrgIDAndProjectID(v.Db, userGrantTable, orgID, projectID) } -func (v *View) PutUserGrant(grant *model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUserGrant(grant *model.UserGrantView, event *models.Event) error { err := view.PutUserGrant(v.Db, userGrantTable, grant) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence, eventTimestamp) + return v.ProcessedUserGrantSequence(event) } -func (v *View) PutUserGrants(grants []*model.UserGrantView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUserGrants(grants []*model.UserGrantView, event *models.Event) error { err := view.PutUserGrants(v.Db, userGrantTable, grants...) if err != nil { return err } - return v.ProcessedUserGrantSequence(sequence, eventTimestamp) + return v.ProcessedUserGrantSequence(event) } -func (v *View) DeleteUserGrant(grantID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserGrant(grantID string, event *models.Event) error { err := view.DeleteUserGrant(v.Db, userGrantTable, grantID) if err != nil { return nil } - return v.ProcessedUserGrantSequence(eventSequence, eventTimestamp) + return v.ProcessedUserGrantSequence(event) } -func (v *View) GetLatestUserGrantSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userGrantTable) +func (v *View) GetLatestUserGrantSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userGrantTable, aggregateType) } -func (v *View) ProcessedUserGrantSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userGrantTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserGrantSequence(event *models.Event) error { + return v.saveCurrentSequence(userGrantTable, event) } func (v *View) UpdateUserGrantSpoolerRunTimestamp() error { diff --git a/internal/management/repository/eventsourcing/view/user_membership.go b/internal/management/repository/eventsourcing/view/user_membership.go index 4c733dc875..fe80081194 100644 --- a/internal/management/repository/eventsourcing/view/user_membership.go +++ b/internal/management/repository/eventsourcing/view/user_membership.go @@ -1,11 +1,11 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -24,60 +24,60 @@ func (v *View) SearchUserMemberships(request *usr_model.UserMembershipSearchRequ return view.SearchUserMemberships(v.Db, userMembershipTable, request) } -func (v *View) PutUserMembership(membership *model.UserMembershipView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutUserMembership(membership *model.UserMembershipView, event *models.Event) error { err := view.PutUserMembership(v.Db, userMembershipTable, membership) if err != nil { return err } - return v.ProcessedUserMembershipSequence(sequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, sequence uint64, eventTimestamp time.Time) error { +func (v *View) BulkPutUserMemberships(memberships []*model.UserMembershipView, event *models.Event) error { err := view.PutUserMemberships(v.Db, userMembershipTable, memberships...) if err != nil { return err } - return v.ProcessedUserMembershipSequence(sequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserMembership(userID, aggregateID, objectID string, memberType usr_model.MemberType, event *models.Event) error { err := view.DeleteUserMembership(v.Db, userMembershipTable, userID, aggregateID, objectID, memberType) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) DeleteUserMembershipsByUserID(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserMembershipsByUserID(userID string, event *models.Event) error { err := view.DeleteUserMembershipsByUserID(v.Db, userMembershipTable, userID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) DeleteUserMembershipsByAggregateID(aggregateID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserMembershipsByAggregateID(aggregateID string, event *models.Event) error { err := view.DeleteUserMembershipsByAggregateID(v.Db, userMembershipTable, aggregateID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) DeleteUserMembershipsByAggregateIDAndObjectID(aggregateID, objectID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteUserMembershipsByAggregateIDAndObjectID(aggregateID, objectID string, event *models.Event) error { err := view.DeleteUserMembershipsByAggregateIDAndObjectID(v.Db, userMembershipTable, aggregateID, objectID) if err != nil { return nil } - return v.ProcessedUserMembershipSequence(eventSequence, eventTimestamp) + return v.ProcessedUserMembershipSequence(event) } -func (v *View) GetLatestUserMembershipSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(userMembershipTable) +func (v *View) GetLatestUserMembershipSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(userMembershipTable, aggregateType) } -func (v *View) ProcessedUserMembershipSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(userMembershipTable, eventSequence, eventTimestamp) +func (v *View) ProcessedUserMembershipSequence(event *models.Event) error { + return v.saveCurrentSequence(userMembershipTable, event) } func (v *View) UpdateUserMembershipSpoolerRunTimestamp() error { diff --git a/internal/notification/repository/eventsourcing/handler/handler.go b/internal/notification/repository/eventsourcing/handler/handler.go index a6db3edb74..aaf553ebdf 100644 --- a/internal/notification/repository/eventsourcing/handler/handler.go +++ b/internal/notification/repository/eventsourcing/handler/handler.go @@ -1,6 +1,9 @@ package handler import ( + "net/http" + "time" + "github.com/caos/logging" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/config/types" @@ -12,8 +15,6 @@ import ( "github.com/caos/zitadel/internal/notification/repository/eventsourcing/view" org_event "github.com/caos/zitadel/internal/org/repository/eventsourcing" usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing" - "net/http" - "time" ) type Configs map[string]*Config @@ -27,6 +28,12 @@ type handler struct { bulkLimit uint64 cycleDuration time.Duration errorCountUntilSkip uint64 + + es eventstore.Eventstore +} + +func (h *handler) Eventstore() eventstore.Eventstore { + return h.es } type EventstoreRepos struct { @@ -35,34 +42,33 @@ type EventstoreRepos struct { IAMEvents *iam_es.IAMEventstore } -func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, eventstore eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults, i18n *i18n.Translator, dir http.FileSystem) []query.Handler { +func Register(configs Configs, bulkLimit, errorCount uint64, view *view.View, es eventstore.Eventstore, repos EventstoreRepos, systemDefaults sd.SystemDefaults, i18n *i18n.Translator, dir http.FileSystem) []query.Handler { aesCrypto, err := crypto.NewAESCrypto(systemDefaults.UserVerificationKey) if err != nil { logging.Log("HANDL-s90ew").WithError(err).Debug("error create new aes crypto") } return []query.Handler{ - &NotifyUser{ - handler: handler{view, bulkLimit, configs.cycleDuration("User"), errorCount}, - orgEvents: repos.OrgEvents, - iamEvents: repos.IAMEvents, - iamID: systemDefaults.IamID, - }, - &Notification{ - handler: handler{view, bulkLimit, configs.cycleDuration("Notification"), errorCount}, - eventstore: eventstore, - userEvents: repos.UserEvents, - systemDefaults: systemDefaults, - AesCrypto: aesCrypto, - i18n: i18n, - statikDir: dir, - }, + newNotifyUser( + handler{view, bulkLimit, configs.cycleDuration("User"), errorCount, es}, + repos.OrgEvents, + repos.IAMEvents, + systemDefaults.IamID, + ), + newNotification( + handler{view, bulkLimit, configs.cycleDuration("Notification"), errorCount, es}, + repos.UserEvents, + systemDefaults, + aesCrypto, + i18n, + dir, + ), } } func (configs Configs) cycleDuration(viewModel string) time.Duration { c, ok := configs[viewModel] if !ok { - return 1 * time.Second + return 3 * time.Minute } return c.MinimumCycleDuration.Duration } diff --git a/internal/notification/repository/eventsourcing/handler/notification.go b/internal/notification/repository/eventsourcing/handler/notification.go index 96ff4ae9ce..cebde591bf 100644 --- a/internal/notification/repository/eventsourcing/handler/notification.go +++ b/internal/notification/repository/eventsourcing/handler/notification.go @@ -7,34 +7,22 @@ import ( "time" "github.com/caos/logging" - "github.com/caos/zitadel/internal/api/authz" sd "github.com/caos/zitadel/internal/config/systemdefaults" "github.com/caos/zitadel/internal/crypto" - "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/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" "github.com/caos/zitadel/internal/i18n" iam_model "github.com/caos/zitadel/internal/iam/model" iam_es_model "github.com/caos/zitadel/internal/iam/repository/view/model" "github.com/caos/zitadel/internal/notification/types" - "github.com/caos/zitadel/internal/user/repository/eventsourcing" usr_event "github.com/caos/zitadel/internal/user/repository/eventsourcing" es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" ) -type Notification struct { - handler - eventstore eventstore.Eventstore - userEvents *usr_event.UserEventstore - systemDefaults sd.SystemDefaults - AesCrypto crypto.EncryptionAlgorithm - i18n *i18n.Translator - statikDir http.FileSystem -} - const ( notificationTable = "notification.notifications" NotifyUserID = "NOTIFICATION" @@ -42,16 +30,69 @@ const ( labelPolicyTableDef = "adminapi.label_policies" ) +type Notification struct { + handler + userEvents *usr_event.UserEventstore + systemDefaults sd.SystemDefaults + AesCrypto crypto.EncryptionAlgorithm + i18n *i18n.Translator + statikDir http.FileSystem + subscription *eventstore.Subscription +} + +func newNotification( + handler handler, + userEvents *usr_event.UserEventstore, + defaults sd.SystemDefaults, + aesCrypto crypto.EncryptionAlgorithm, + translator *i18n.Translator, + statikDir http.FileSystem, +) *Notification { + h := &Notification{ + handler: handler, + userEvents: userEvents, + systemDefaults: defaults, + i18n: translator, + statikDir: statikDir, + AesCrypto: aesCrypto, + } + + h.subscribe() + + return h +} + +func (k *Notification) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (n *Notification) ViewModel() string { return notificationTable } +func (_ *Notification) AggregateTypes() []models.AggregateType { + return []models.AggregateType{es_model.UserAggregate} +} + +func (n *Notification) CurrentSequence(event *models.Event) (uint64, error) { + sequence, err := n.view.GetLatestNotificationSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + func (n *Notification) EventQuery() (*models.SearchQuery, error) { - sequence, err := n.view.GetLatestNotificationSequence() + sequence, err := n.view.GetLatestNotificationSequence("") if err != nil { return nil, err } - return eventsourcing.UserQuery(sequence.CurrentSequence), nil + return usr_event.UserQuery(sequence.CurrentSequence), nil } func (n *Notification) Reduce(event *models.Event) (err error) { @@ -71,12 +112,12 @@ func (n *Notification) Reduce(event *models.Event) (err error) { case es_model.DomainClaimed: err = n.handleDomainClaimed(event) default: - return n.view.ProcessedNotificationSequence(event.Sequence, event.CreationDate) + return n.view.ProcessedNotificationSequence(event) } if err != nil { return err } - return n.view.ProcessedNotificationSequence(event.Sequence, event.CreationDate) + return n.view.ProcessedNotificationSequence(event) } func (n *Notification) handleInitUserCode(event *models.Event) (err error) { @@ -229,12 +270,12 @@ func (n *Notification) checkIfAlreadyHandled(userID string, sequence uint64, eve } func (n *Notification) getUserEvents(userID string, sequence uint64) ([]*models.Event, error) { - query, err := eventsourcing.UserByIDQuery(userID, sequence) + query, err := usr_event.UserByIDQuery(userID, sequence) if err != nil { return nil, err } - return n.eventstore.FilterEvents(context.Background(), query) + return n.es.FilterEvents(context.Background(), query) } func (n *Notification) OnError(event *models.Event, err error) error { @@ -254,7 +295,7 @@ func getSetNotifyContextData(orgID string) context.Context { func (n *Notification) getLabelPolicy(ctx context.Context) (*iam_model.LabelPolicyView, error) { // read from Org policy, err := n.view.LabelPolicyByAggregateID(authz.GetCtxData(ctx).OrgID, labelPolicyTableOrg) - if errors.IsNotFound(err) { + if caos_errs.IsNotFound(err) { // read from default policy, err = n.view.LabelPolicyByAggregateID(n.systemDefaults.IamID, labelPolicyTableDef) if err != nil { diff --git a/internal/notification/repository/eventsourcing/handler/notify_user.go b/internal/notification/repository/eventsourcing/handler/notify_user.go index b41cd93ce7..4b82a16c0c 100644 --- a/internal/notification/repository/eventsourcing/handler/notify_user.go +++ b/internal/notification/repository/eventsourcing/handler/notify_user.go @@ -2,14 +2,13 @@ package handler import ( "context" - iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing" "github.com/caos/logging" - "github.com/caos/zitadel/internal/eventstore" - "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/eventstore/query" "github.com/caos/zitadel/internal/eventstore/spooler" + iam_es "github.com/caos/zitadel/internal/iam/repository/eventsourcing" org_model "github.com/caos/zitadel/internal/org/model" org_events "github.com/caos/zitadel/internal/org/repository/eventsourcing" org_es_model "github.com/caos/zitadel/internal/org/repository/eventsourcing/model" @@ -17,33 +16,72 @@ import ( view_model "github.com/caos/zitadel/internal/user/repository/view/model" ) -type NotifyUser struct { - handler - eventstore eventstore.Eventstore - orgEvents *org_events.OrgEventstore - iamEvents *iam_es.IAMEventstore - iamID string -} - const ( userTable = "notification.notify_users" ) +type NotifyUser struct { + handler + orgEvents *org_events.OrgEventstore + iamEvents *iam_es.IAMEventstore + iamID string + subscription *eventstore.Subscription +} + +func newNotifyUser( + handler handler, + orgEvents *org_events.OrgEventstore, + iamEvents *iam_es.IAMEventstore, + iamID string, +) *NotifyUser { + h := &NotifyUser{ + handler: handler, + orgEvents: orgEvents, + iamEvents: iamEvents, + iamID: iamID, + } + + h.subscribe() + + return h +} + +func (k *NotifyUser) subscribe() { + k.subscription = k.es.Subscribe(k.AggregateTypes()...) + go func() { + for event := range k.subscription.Events { + query.ReduceEvent(k, event) + } + }() +} + func (p *NotifyUser) ViewModel() string { return userTable } -func (p *NotifyUser) EventQuery() (*models.SearchQuery, error) { - sequence, err := p.view.GetLatestNotifyUserSequence() +func (_ *NotifyUser) AggregateTypes() []es_models.AggregateType { + return []es_models.AggregateType{es_model.UserAggregate, org_es_model.OrgAggregate} +} + +func (p *NotifyUser) CurrentSequence(event *es_models.Event) (uint64, error) { + sequence, err := p.view.GetLatestNotifyUserSequence(string(event.AggregateType)) + if err != nil { + return 0, err + } + return sequence.CurrentSequence, nil +} + +func (p *NotifyUser) EventQuery() (*es_models.SearchQuery, error) { + sequence, err := p.view.GetLatestNotifyUserSequence("") if err != nil { return nil, err } return es_models.NewSearchQuery(). - AggregateTypeFilter(es_model.UserAggregate, org_es_model.OrgAggregate). + AggregateTypeFilter(p.AggregateTypes()...). LatestSequenceFilter(sequence.CurrentSequence), nil } -func (u *NotifyUser) Reduce(event *models.Event) (err error) { +func (u *NotifyUser) Reduce(event *es_models.Event) (err error) { switch event.AggregateType { case es_model.UserAggregate: return u.ProcessUser(event) @@ -54,7 +92,7 @@ func (u *NotifyUser) Reduce(event *models.Event) (err error) { } } -func (u *NotifyUser) ProcessUser(event *models.Event) (err error) { +func (u *NotifyUser) ProcessUser(event *es_models.Event) (err error) { user := new(view_model.NotifyUser) switch event.Type { case es_model.UserAdded, @@ -93,17 +131,17 @@ func (u *NotifyUser) ProcessUser(event *models.Event) (err error) { } u.fillLoginNames(user) case es_model.UserRemoved: - return u.view.DeleteNotifyUser(event.AggregateID, event.Sequence, event.CreationDate) + return u.view.DeleteNotifyUser(event.AggregateID, event) default: - return u.view.ProcessedNotifyUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedNotifyUserSequence(event) } if err != nil { return err } - return u.view.PutNotifyUser(user, user.Sequence, event.CreationDate) + return u.view.PutNotifyUser(user, event) } -func (u *NotifyUser) ProcessOrg(event *models.Event) (err error) { +func (u *NotifyUser) ProcessOrg(event *es_models.Event) (err error) { switch event.Type { case org_es_model.OrgDomainVerified, org_es_model.OrgDomainRemoved, @@ -114,11 +152,11 @@ func (u *NotifyUser) ProcessOrg(event *models.Event) (err error) { case org_es_model.OrgDomainPrimarySet: return u.fillPreferredLoginNamesOnOrgUsers(event) default: - return u.view.ProcessedNotifyUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedNotifyUserSequence(event) } } -func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *models.Event) error { +func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *es_models.Event) error { org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner)) if err != nil { return err @@ -136,15 +174,15 @@ func (u *NotifyUser) fillLoginNamesOnOrgUsers(event *models.Event) error { } for _, user := range users { user.SetLoginNames(policy, org.Domains) - err := u.view.PutNotifyUser(user, 0, event.CreationDate) + err := u.view.PutNotifyUser(user, event) if err != nil { return err } } - return u.view.ProcessedNotifyUserSequence(event.Sequence, event.CreationDate) + return u.view.ProcessedNotifyUserSequence(event) } -func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *models.Event) error { +func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *es_models.Event) error { org, err := u.orgEvents.OrgByID(context.Background(), org_model.NewOrg(event.ResourceOwner)) if err != nil { return err @@ -165,7 +203,7 @@ func (u *NotifyUser) fillPreferredLoginNamesOnOrgUsers(event *models.Event) erro } for _, user := range users { user.PreferredLoginName = user.GenerateLoginName(org.GetPrimaryDomain().Domain, policy.UserLoginMustBeDomain) - err := u.view.PutNotifyUser(user, 0, event.CreationDate) + err := u.view.PutNotifyUser(user, event) if err != nil { return err } @@ -190,7 +228,7 @@ func (u *NotifyUser) fillLoginNames(user *view_model.NotifyUser) (err error) { return nil } -func (p *NotifyUser) OnError(event *models.Event, err error) error { +func (p *NotifyUser) OnError(event *es_models.Event, err error) error { logging.LogWithFields("SPOOL-9spwf", "id", event.AggregateID).WithError(err).Warn("something went wrong in notify user handler") return spooler.HandleError(event, err, p.view.GetLatestNotifyUserFailedEvent, p.view.ProcessedNotifyUserFailedEvent, p.view.ProcessedNotifyUserSequence, p.errorCountUntilSkip) } diff --git a/internal/notification/repository/eventsourcing/spooler/lock.go b/internal/notification/repository/eventsourcing/spooler/lock.go index 46325b1495..fe14ec49fc 100644 --- a/internal/notification/repository/eventsourcing/spooler/lock.go +++ b/internal/notification/repository/eventsourcing/spooler/lock.go @@ -2,7 +2,6 @@ package spooler import ( "database/sql" - es_locker "github.com/caos/zitadel/internal/eventstore/locker" "time" ) @@ -15,5 +14,5 @@ type locker struct { } func (l *locker) Renew(lockerID, viewModel string, waitTime time.Duration) error { - return es_locker.Renew(l.dbClient, lockTable, lockerID, viewModel, waitTime) + return nil } diff --git a/internal/notification/repository/eventsourcing/view/notification.go b/internal/notification/repository/eventsourcing/view/notification.go index baeb75e162..b14242f47e 100644 --- a/internal/notification/repository/eventsourcing/view/notification.go +++ b/internal/notification/repository/eventsourcing/view/notification.go @@ -1,20 +1,20 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( notificationTable = "notification.notifications" ) -func (v *View) GetLatestNotificationSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(notificationTable) +func (v *View) GetLatestNotificationSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(notificationTable, aggregateType) } -func (v *View) ProcessedNotificationSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(notificationTable, eventSequence, eventTimestamp) +func (v *View) ProcessedNotificationSequence(event *models.Event) error { + return v.saveCurrentSequence(notificationTable, event) } func (v *View) UpdateNotificationSpoolerRunTimestamp() error { diff --git a/internal/notification/repository/eventsourcing/view/notify_user.go b/internal/notification/repository/eventsourcing/view/notify_user.go index 44d1a1e32b..b7a24899f7 100644 --- a/internal/notification/repository/eventsourcing/view/notify_user.go +++ b/internal/notification/repository/eventsourcing/view/notify_user.go @@ -1,10 +1,10 @@ package view import ( + "github.com/caos/zitadel/internal/eventstore/models" "github.com/caos/zitadel/internal/user/repository/view" "github.com/caos/zitadel/internal/user/repository/view/model" "github.com/caos/zitadel/internal/view/repository" - "time" ) const ( @@ -15,13 +15,13 @@ func (v *View) NotifyUserByID(userID string) (*model.NotifyUser, error) { return view.NotifyUserByID(v.Db, notifyUserTable, userID) } -func (v *View) PutNotifyUser(user *model.NotifyUser, sequence uint64, eventTimestamp time.Time) error { +func (v *View) PutNotifyUser(user *model.NotifyUser, event *models.Event) error { err := view.PutNotifyUser(v.Db, notifyUserTable, user) if err != nil { return err } - if sequence != 0 { - return v.ProcessedNotifyUserSequence(sequence, eventTimestamp) + if event.Sequence != 0 { + return v.ProcessedNotifyUserSequence(event) } return nil } @@ -30,20 +30,20 @@ func (v *View) NotifyUsersByOrgID(orgID string) ([]*model.NotifyUser, error) { return view.NotifyUsersByOrgID(v.Db, notifyUserTable, orgID) } -func (v *View) DeleteNotifyUser(userID string, eventSequence uint64, eventTimestamp time.Time) error { +func (v *View) DeleteNotifyUser(userID string, event *models.Event) error { err := view.DeleteNotifyUser(v.Db, notifyUserTable, userID) if err != nil { return nil } - return v.ProcessedNotifyUserSequence(eventSequence, eventTimestamp) + return v.ProcessedNotifyUserSequence(event) } -func (v *View) GetLatestNotifyUserSequence() (*repository.CurrentSequence, error) { - return v.latestSequence(notifyUserTable) +func (v *View) GetLatestNotifyUserSequence(aggregateType string) (*repository.CurrentSequence, error) { + return v.latestSequence(notifyUserTable, aggregateType) } -func (v *View) ProcessedNotifyUserSequence(eventSequence uint64, eventTimestamp time.Time) error { - return v.saveCurrentSequence(notifyUserTable, eventSequence, eventTimestamp) +func (v *View) ProcessedNotifyUserSequence(event *models.Event) error { + return v.saveCurrentSequence(notifyUserTable, event) } func (v *View) UpdateNotifyUserSpoolerRunTimestamp() error { diff --git a/internal/notification/repository/eventsourcing/view/sequence.go b/internal/notification/repository/eventsourcing/view/sequence.go index f1868e4f44..8d56cc19b9 100644 --- a/internal/notification/repository/eventsourcing/view/sequence.go +++ b/internal/notification/repository/eventsourcing/view/sequence.go @@ -1,24 +1,26 @@ package view import ( - "github.com/caos/zitadel/internal/view/repository" "time" + + "github.com/caos/zitadel/internal/eventstore/models" + "github.com/caos/zitadel/internal/view/repository" ) const ( sequencesTable = "notification.current_sequences" ) -func (v *View) saveCurrentSequence(viewName string, sequence uint64, eventTimestamp time.Time) error { - return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, sequence, eventTimestamp) +func (v *View) saveCurrentSequence(viewName string, event *models.Event) error { + return repository.SaveCurrentSequence(v.Db, sequencesTable, viewName, string(event.AggregateType), event.Sequence, event.CreationDate) } -func (v *View) latestSequence(viewName string) (*repository.CurrentSequence, error) { - return repository.LatestSequence(v.Db, sequencesTable, viewName) +func (v *View) latestSequence(viewName, aggregateType string) (*repository.CurrentSequence, error) { + return repository.LatestSequence(v.Db, sequencesTable, viewName, aggregateType) } func (v *View) updateSpoolerRunSequence(viewName string) error { - currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName) + currentSequence, err := repository.LatestSequence(v.Db, sequencesTable, viewName, "") if err != nil { return err } @@ -26,5 +28,8 @@ func (v *View) updateSpoolerRunSequence(viewName string) error { currentSequence.ViewName = viewName } currentSequence.LastSuccessfulSpoolerRun = time.Now() + //update all aggregate types + //TODO: not sure if all scenarios work as expected + currentSequence.AggregateType = "" return repository.UpdateCurrentSequence(v.Db, sequencesTable, currentSequence) } diff --git a/internal/org/repository/view/org_member_view.go b/internal/org/repository/view/org_member_view.go index ef52864b52..c9035d38dc 100644 --- a/internal/org/repository/view/org_member_view.go +++ b/internal/org/repository/view/org_member_view.go @@ -17,7 +17,7 @@ func OrgMemberByIDs(db *gorm.DB, table, orgID, userID string) (*model.OrgMemberV query := repository.PrepareGetByQuery(table, orgIDQuery, userIDQuery) err := query(db, member) if caos_errs.IsNotFound(err) { - return nil, caos_errs.ThrowNotFound(nil, "VIEW-DG1qh", "Errors.Org.MemberNotFound") + return nil, caos_errs.ThrowNotFound(nil, "VIEW-gIaTM", "Errors.Org.MemberNotFound") } return member, err } diff --git a/internal/user/repository/view/model/token.go b/internal/user/repository/view/model/token.go index 725132ad52..eb20cf76c9 100644 --- a/internal/user/repository/view/model/token.go +++ b/internal/user/repository/view/model/token.go @@ -2,13 +2,14 @@ package model import ( "encoding/json" + "time" + "github.com/caos/logging" caos_errs "github.com/caos/zitadel/internal/errors" "github.com/caos/zitadel/internal/eventstore/models" es_models "github.com/caos/zitadel/internal/eventstore/models" usr_model "github.com/caos/zitadel/internal/user/model" usr_es_model "github.com/caos/zitadel/internal/user/repository/eventsourcing/model" - "time" "github.com/lib/pq" ) diff --git a/internal/view/model/view.go b/internal/view/model/view.go index 6f766b912b..5cb354a1b7 100644 --- a/internal/view/model/view.go +++ b/internal/view/model/view.go @@ -10,4 +10,5 @@ type View struct { CurrentSequence uint64 EventTimestamp time.Time LastSuccessfulSpoolerRun time.Time + AggregateType string } diff --git a/internal/view/repository/sequence.go b/internal/view/repository/sequence.go index 10023b2b66..056787a5a7 100644 --- a/internal/view/repository/sequence.go +++ b/internal/view/repository/sequence.go @@ -1,11 +1,13 @@ package repository import ( - caos_errs "github.com/caos/zitadel/internal/errors" - "github.com/caos/zitadel/internal/view/model" - "github.com/jinzhu/gorm" "strings" "time" + + caos_errs "github.com/caos/zitadel/internal/errors" + int_model "github.com/caos/zitadel/internal/model" + "github.com/caos/zitadel/internal/view/model" + "github.com/jinzhu/gorm" ) type CurrentSequence struct { @@ -13,6 +15,18 @@ type CurrentSequence struct { CurrentSequence uint64 `gorm:"column:current_sequence"` EventTimestamp time.Time `gorm:"column:event_timestamp"` LastSuccessfulSpoolerRun time.Time `gorm:"column:last_successful_spooler_run"` + AggregateType string `gorm:"column:aggregate_type;primary_key"` +} + +type currentSequenceViewWithSequence struct { + ViewName string `gorm:"column:view_name;primary_key"` + CurrentSequence uint64 `gorm:"column:current_sequence"` + LastSuccessfulSpoolerRun time.Time `gorm:"column:last_successful_spooler_run"` +} + +type currentSequenceView struct { + ViewName string `gorm:"column:view_name;primary_key"` + LastSuccessfulSpoolerRun time.Time `gorm:"column:last_successful_spooler_run"` } type SequenceSearchKey int32 @@ -20,6 +34,7 @@ type SequenceSearchKey int32 const ( SequenceSearchKeyUndefined SequenceSearchKey = iota SequenceSearchKeyViewName + SequenceSearchKeyAggregateType ) type sequenceSearchKey SequenceSearchKey @@ -28,11 +43,30 @@ func (key sequenceSearchKey) ToColumnName() string { switch SequenceSearchKey(key) { case SequenceSearchKeyViewName: return "view_name" + case SequenceSearchKeyAggregateType: + return "aggregate_type" default: return "" } } +type sequenceSearchQuery struct { + key sequenceSearchKey + value string +} + +func (q *sequenceSearchQuery) GetKey() ColumnKey { + return q.key +} + +func (q *sequenceSearchQuery) GetMethod() int_model.SearchMethod { + return int_model.SearchMethodEquals +} + +func (q *sequenceSearchQuery) GetValue() interface{} { + return q.value +} + func CurrentSequenceToModel(sequence *CurrentSequence) *model.View { dbView := strings.Split(sequence.ViewName, ".") return &model.View{ @@ -41,26 +75,44 @@ func CurrentSequenceToModel(sequence *CurrentSequence) *model.View { CurrentSequence: sequence.CurrentSequence, EventTimestamp: sequence.EventTimestamp, LastSuccessfulSpoolerRun: sequence.LastSuccessfulSpoolerRun, + AggregateType: sequence.AggregateType, } } -func SaveCurrentSequence(db *gorm.DB, table, viewName string, sequence uint64, eventTimestamp time.Time) error { - return UpdateCurrentSequence(db, table, &CurrentSequence{viewName, sequence, eventTimestamp, time.Now()}) +func SaveCurrentSequence(db *gorm.DB, table, viewName, aggregateType string, sequence uint64, eventTimestamp time.Time) error { + return UpdateCurrentSequence(db, table, &CurrentSequence{viewName, sequence, eventTimestamp, time.Now(), aggregateType}) } -func UpdateCurrentSequence(db *gorm.DB, table string, currentSequence *CurrentSequence) error { - save := PrepareSave(table) - err := save(db, currentSequence) +func UpdateCurrentSequence(db *gorm.DB, table string, currentSequence *CurrentSequence) (err error) { + var seq interface{} = currentSequence + if currentSequence.AggregateType == "" && currentSequence.CurrentSequence > 0 { + //spooler run + seq = ¤tSequenceView{ViewName: currentSequence.ViewName, LastSuccessfulSpoolerRun: currentSequence.LastSuccessfulSpoolerRun} + } else if currentSequence.AggregateType == "" { + //reset current sequence on view + seq = ¤tSequenceViewWithSequence{ViewName: currentSequence.ViewName, LastSuccessfulSpoolerRun: currentSequence.LastSuccessfulSpoolerRun, CurrentSequence: currentSequence.CurrentSequence} + } + save := PrepareSave(table) + err = save(db, seq) if err != nil { return caos_errs.ThrowInternal(err, "VIEW-5kOhP", "unable to updated processed sequence") } return nil } -func LatestSequence(db *gorm.DB, table, viewName string) (*CurrentSequence, error) { +func LatestSequence(db *gorm.DB, table, viewName, aggregateType string) (*CurrentSequence, error) { + searchQueries := make([]SearchQuery, 0, 2) + searchQueries = append(searchQueries, &sequenceSearchQuery{key: sequenceSearchKey(SequenceSearchKeyViewName), value: viewName}) + if aggregateType != "" { + searchQueries = append(searchQueries, &sequenceSearchQuery{key: sequenceSearchKey(SequenceSearchKeyAggregateType), value: aggregateType}) + } else { + // ensure highest sequence of view + db = db.Order("current_sequence DESC") + } + + query := PrepareGetByQuery(table, searchQueries...) sequence := new(CurrentSequence) - query := PrepareGetByKey(table, sequenceSearchKey(SequenceSearchKeyViewName), viewName) err := query(db, sequence) if err == nil { @@ -89,5 +141,5 @@ func ClearView(db *gorm.DB, truncateView, sequenceTable string) error { if err != nil { return err } - return SaveCurrentSequence(db, sequenceTable, truncateView, 0, time.Now()) + return SaveCurrentSequence(db, sequenceTable, truncateView, "", 0, time.Now()) } diff --git a/migrations/cockroach/V1.26__current_sequence_table.sql b/migrations/cockroach/V1.26__current_sequence_table.sql new file mode 100644 index 0000000000..61bf4bb87a --- /dev/null +++ b/migrations/cockroach/V1.26__current_sequence_table.sql @@ -0,0 +1,21 @@ +ALTER TABLE management.current_sequences ADD COLUMN aggregate_type STRING NOT NULL DEFAULT ''; +ALTER TABLE auth.current_sequences ADD COLUMN aggregate_type STRING NOT NULL DEFAULT ''; +ALTER TABLE authz.current_sequences ADD COLUMN aggregate_type STRING NOT NULL DEFAULT ''; +ALTER TABLE adminapi.current_sequences ADD COLUMN aggregate_type STRING NOT NULL DEFAULT ''; +ALTER TABLE notification.current_sequences ADD COLUMN aggregate_type STRING NOT NULL DEFAULT ''; + +BEGIN; + +ALTER TABLE management.current_sequences DROP CONSTRAINT "primary"; +ALTER TABLE auth.current_sequences DROP CONSTRAINT "primary"; +ALTER TABLE authz.current_sequences DROP CONSTRAINT "primary"; +ALTER TABLE adminapi.current_sequences DROP CONSTRAINT "primary"; +ALTER TABLE notification.current_sequences DROP CONSTRAINT "primary"; + +ALTER TABLE management.current_sequences ADD CONSTRAINT "primary" PRIMARY KEY (view_name, aggregate_type); +ALTER TABLE auth.current_sequences ADD CONSTRAINT "primary" PRIMARY KEY (view_name, aggregate_type); +ALTER TABLE authz.current_sequences ADD CONSTRAINT "primary" PRIMARY KEY (view_name, aggregate_type); +ALTER TABLE adminapi.current_sequences ADD CONSTRAINT "primary" PRIMARY KEY (view_name, aggregate_type); +ALTER TABLE notification.current_sequences ADD CONSTRAINT "primary" PRIMARY KEY (view_name, aggregate_type); + +COMMIT; \ No newline at end of file diff --git a/pkg/grpc/management/mock/management.proto.mock.go b/pkg/grpc/management/mock/management.proto.mock.go index b76d47eaf5..28011d98d1 100644 --- a/pkg/grpc/management/mock/management.proto.mock.go +++ b/pkg/grpc/management/mock/management.proto.mock.go @@ -1836,6 +1836,46 @@ func (mr *MockManagementServiceClientMockRecorder) RemoveLoginPolicy(arg0, arg1 return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveLoginPolicy", reflect.TypeOf((*MockManagementServiceClient)(nil).RemoveLoginPolicy), varargs...) } +// RemoveMfaOTP mocks base method +func (m *MockManagementServiceClient) RemoveMfaOTP(arg0 context.Context, arg1 *management.UserID, arg2 ...grpc.CallOption) (*emptypb.Empty, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RemoveMfaOTP", varargs...) + ret0, _ := ret[0].(*emptypb.Empty) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RemoveMfaOTP indicates an expected call of RemoveMfaOTP +func (mr *MockManagementServiceClientMockRecorder) RemoveMfaOTP(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveMfaOTP", reflect.TypeOf((*MockManagementServiceClient)(nil).RemoveMfaOTP), varargs...) +} + +// RemoveMfaU2F mocks base method +func (m *MockManagementServiceClient) RemoveMfaU2F(arg0 context.Context, arg1 *management.WebAuthNTokenID, arg2 ...grpc.CallOption) (*emptypb.Empty, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RemoveMfaU2F", varargs...) + ret0, _ := ret[0].(*emptypb.Empty) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RemoveMfaU2F indicates an expected call of RemoveMfaU2F +func (mr *MockManagementServiceClientMockRecorder) RemoveMfaU2F(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveMfaU2F", reflect.TypeOf((*MockManagementServiceClient)(nil).RemoveMfaU2F), varargs...) +} + // RemoveMultiFactorFromLoginPolicy mocks base method func (m *MockManagementServiceClient) RemoveMultiFactorFromLoginPolicy(arg0 context.Context, arg1 *management.MultiFactor, arg2 ...grpc.CallOption) (*emptypb.Empty, error) { m.ctrl.T.Helper()