From f4bd5ddcbcb0fadc9911f2eb9d3c7ab368cb6f19 Mon Sep 17 00:00:00 2001 From: adlerhurst Date: Fri, 6 Nov 2020 13:47:27 +0100 Subject: [PATCH] try splitt event --- internal/eventstore/v2/event.go | 56 ++-- internal/eventstore/v2/event_base.go | 78 +++++ internal/eventstore/v2/eventstore.go | 14 +- internal/eventstore/v2/eventstore_test.go | 281 ++++++++++-------- internal/eventstore/v2/example_test.go | 151 +++++----- internal/eventstore/v2/read_model.go | 8 +- internal/v2/repository/iam/aggregate.go | 36 +++ internal/v2/repository/member/event_added.go | 30 ++ .../v2/repository/member/event_removed.go | 19 ++ 9 files changed, 428 insertions(+), 245 deletions(-) create mode 100644 internal/eventstore/v2/event_base.go create mode 100644 internal/v2/repository/iam/aggregate.go create mode 100644 internal/v2/repository/member/event_added.go create mode 100644 internal/v2/repository/member/event_removed.go diff --git a/internal/eventstore/v2/event.go b/internal/eventstore/v2/event.go index 2883f95e89..37a0824bdb 100644 --- a/internal/eventstore/v2/event.go +++ b/internal/eventstore/v2/event.go @@ -2,18 +2,12 @@ package eventstore import ( "time" - - "github.com/caos/zitadel/internal/eventstore/v2/repository" ) -//Event is the representation of a state change -type Event interface { - //CheckPrevious ensures the event order if true - // if false the previous sequence is not checked on push - CheckPrevious() bool - //EditorService must return the name of the service which creates the new event +type EventPusher interface { + // EditorService is the service who wants to push the event EditorService() string - //EditorUser must return the id of the user who created the event + //EditorUser is the user who wants to push the event EditorUser() string //Type must return an event type which should be unique in the aggregate Type() EventType @@ -24,30 +18,30 @@ type Event interface { // * struct which can be marshalled to json // * pointer to struct which can be marshalled to json Data() interface{} - //MetaData returns all data saved on a event - // It must not be set on push - // The event mapper function must set this struct - MetaData() *EventMetaData + //CheckPrevious ensures the event order if true + // if false the previous sequence is not checked on push + CheckPrevious() bool } -func MetaDataFromRepo(event *repository.Event) *EventMetaData { - return &EventMetaData{ - AggregateID: event.AggregateID, - AggregateType: AggregateType(event.AggregateType), - AggregateVersion: Version(event.Version), - PreviouseSequence: event.PreviousSequence, - ResourceOwner: event.ResourceOwner, - Sequence: event.Sequence, - CreationDate: event.CreationDate, - } +type EventReader interface { + // EditorService is the service who pushed the event + EditorService() string + //EditorUser is the user who pushed the event + EditorUser() string + //Type is the type of the event + Type() EventType + + AggregateID() string + AggregateType() AggregateType + ResourceOwner() string + AggregateVersion() Version + Sequence() uint64 + PreviousSequence() uint64 + CreationDate() time.Time } -type EventMetaData struct { - AggregateID string - AggregateType AggregateType - ResourceOwner string - AggregateVersion Version - Sequence uint64 - PreviouseSequence uint64 - CreationDate time.Time +//Event is the representation of a state change +type Event interface { + EventPusher + EventReader } diff --git a/internal/eventstore/v2/event_base.go b/internal/eventstore/v2/event_base.go new file mode 100644 index 0000000000..f303a1cab5 --- /dev/null +++ b/internal/eventstore/v2/event_base.go @@ -0,0 +1,78 @@ +package eventstore + +import ( + "time" + + "github.com/caos/zitadel/internal/eventstore/v2/repository" +) + +type BaseEvent struct { + aggregateID string `json:"-"` + aggregateType AggregateType `json:"-"` + EventType EventType `json:"-"` + + resourceOwner string `json:"-"` + aggregateVersion Version `json:"-"` + sequence uint64 `json:"-"` + previouseSequence uint64 `json:"-"` + creationDate time.Time `json:"-"` + + //User is the user who created the event + User string `json:"-"` + //Service is the service which created the event + Service string `json:"-"` +} + +// EditorService implements EventPusher +func (e *BaseEvent) EditorService() string { + return e.Service +} + +//EditorUser implements EventPusher +func (e *BaseEvent) EditorUser() string { + return e.User +} + +//Type implements EventPusher +func (e *BaseEvent) Type() EventType { + return e.EventType +} + +func (e *BaseEvent) AggregateID() string { + return e.aggregateID +} +func (e *BaseEvent) AggregateType() AggregateType { + return e.aggregateType +} +func (e *BaseEvent) ResourceOwner() string { + return e.resourceOwner +} +func (e *BaseEvent) AggregateVersion() Version { + return e.aggregateVersion +} +func (e *BaseEvent) Sequence() uint64 { + return e.sequence +} +func (e *BaseEvent) PreviousSequence() uint64 { + return e.previouseSequence +} +func (e *BaseEvent) CreationDate() time.Time { + return e.creationDate +} + +func BaseEventFromRepo(event *repository.Event) *BaseEvent { + return &BaseEvent{ + aggregateID: event.AggregateID, + aggregateType: AggregateType(event.AggregateType), + aggregateVersion: Version(event.Version), + EventType: EventType(event.Type), + creationDate: event.CreationDate, + sequence: event.Sequence, + previouseSequence: event.PreviousSequence, + resourceOwner: event.ResourceOwner, + Service: event.EditorService, + User: event.EditorUser, + } +} + +func NewBaseEvent() diff --git a/internal/eventstore/v2/eventstore.go b/internal/eventstore/v2/eventstore.go index 0d48cb860c..f87f55837b 100644 --- a/internal/eventstore/v2/eventstore.go +++ b/internal/eventstore/v2/eventstore.go @@ -42,7 +42,7 @@ type aggregater interface { //Type returns the aggregate type Type() AggregateType //Events returns the events which will be pushed - Events() []Event + Events() []EventPusher //ResourceOwner returns the organisation id which manages this aggregate // resource owner is only on the inital push needed // afterwards the resource owner of the previous event is taken @@ -58,7 +58,7 @@ type aggregater interface { //PushAggregates maps the events of all aggregates to an eventstore event // based on the pushMapper -func (es *Eventstore) PushAggregates(ctx context.Context, aggregates ...aggregater) ([]Event, error) { +func (es *Eventstore) PushAggregates(ctx context.Context, aggregates ...aggregater) ([]EventReader, error) { events, err := es.aggregatesToEvents(aggregates) if err != nil { return nil, err @@ -102,7 +102,7 @@ func (es *Eventstore) aggregatesToEvents(aggregates []aggregater) ([]*repository //FilterEvents filters the stored events based on the searchQuery // and maps the events to the defined event structs -func (es *Eventstore) FilterEvents(ctx context.Context, queryFactory *SearchQueryFactory) ([]Event, error) { +func (es *Eventstore) FilterEvents(ctx context.Context, queryFactory *SearchQueryFactory) ([]EventReader, error) { query, err := queryFactory.build() if err != nil { return nil, err @@ -115,8 +115,8 @@ func (es *Eventstore) FilterEvents(ctx context.Context, queryFactory *SearchQuer return es.mapEvents(events) } -func (es *Eventstore) mapEvents(events []*repository.Event) (mappedEvents []Event, err error) { - mappedEvents = make([]Event, len(events)) +func (es *Eventstore) mapEvents(events []*repository.Event) (mappedEvents []EventReader, err error) { + mappedEvents = make([]EventReader, len(events)) es.interceptorMutex.Lock() defer es.interceptorMutex.Unlock() @@ -140,7 +140,7 @@ type reducer interface { // it only appends the newly added events Reduce() error //AppendEvents appends the passed events to an internal list of events - AppendEvents(...Event) error + AppendEvents(...EventReader) error } //FilterToReducer filters the events based on the search query, appends all events to the reducer and calls it's reduce function @@ -180,7 +180,7 @@ func (es *Eventstore) RegisterFilterEventMapper(eventType EventType, mapper func return es } -func eventData(event Event) ([]byte, error) { +func eventData(event EventPusher) ([]byte, error) { switch data := event.Data().(type) { case nil: return nil, nil diff --git a/internal/eventstore/v2/eventstore_test.go b/internal/eventstore/v2/eventstore_test.go index e0256c6beb..79ffbd19be 100644 --- a/internal/eventstore/v2/eventstore_test.go +++ b/internal/eventstore/v2/eventstore_test.go @@ -13,7 +13,7 @@ import ( type testAggregate struct { id string - events []Event + events []EventPusher previousSequence uint64 } @@ -25,7 +25,7 @@ func (a *testAggregate) Type() AggregateType { return "test.aggregate" } -func (a *testAggregate) Events() []Event { +func (a *testAggregate) Events() []EventPusher { return a.events } @@ -43,38 +43,39 @@ func (a *testAggregate) PreviousSequence() uint64 { // testEvent implements the Event interface type testEvent struct { + BaseEvent + description string shouldCheckPrevious bool data func() interface{} } +func newTestEvent(description string, data func() interface{}, checkPrevious bool) *testEvent { + return &testEvent{ + description: description, + data: data, + shouldCheckPrevious: checkPrevious, + BaseEvent: BaseEvent{ + User: "editorUser", + Service: "editorService", + EventType: "test.event", + }, + } +} + func (e *testEvent) CheckPrevious() bool { return e.shouldCheckPrevious } -func (e *testEvent) EditorService() string { - return "editorService" -} -func (e *testEvent) EditorUser() string { - return "editorUser" -} -func (e *testEvent) Type() EventType { - return "test.event" -} func (e *testEvent) Data() interface{} { return e.data() } -func (e *testEvent) PreviousSequence() uint64 { - return 0 -} - -func (e *testEvent) MetaData() *EventMetaData { - return nil -} - -func testFilterMapper(*repository.Event) (Event, error) { - return &testEvent{description: "hodor"}, nil +func testFilterMapper(event *repository.Event) (Event, error) { + if event == nil { + return newTestEvent("hodor", nil, false), nil + } + return &testEvent{description: "hodor", BaseEvent: *BaseEventFromRepo(event)}, nil } func Test_eventstore_RegisterFilterEventMapper(t *testing.T) { @@ -132,7 +133,7 @@ func Test_eventstore_RegisterFilterEventMapper(t *testing.T) { mapper: testFilterMapper, }, res: res{ - event: &testEvent{description: "hodor"}, + event: newTestEvent("hodor", nil, false), mapperCount: 1, }, }, @@ -148,7 +149,7 @@ func Test_eventstore_RegisterFilterEventMapper(t *testing.T) { mapper: testFilterMapper, }, res: res{ - event: &testEvent{description: "hodor"}, + event: newTestEvent("hodor", nil, false), mapperCount: 2, }, }, @@ -168,7 +169,7 @@ func Test_eventstore_RegisterFilterEventMapper(t *testing.T) { mapper: testFilterMapper, }, res: res{ - event: &testEvent{description: "hodor"}, + event: newTestEvent("hodor", nil, false), mapperCount: 2, }, }, @@ -195,7 +196,7 @@ func Test_eventstore_RegisterFilterEventMapper(t *testing.T) { } if !reflect.DeepEqual(tt.res.event, event) { - t.Errorf("events should be deep equal. \ngot %v\nwant %v", event, tt.res.event) + t.Errorf("events should be deep equal. \ngot %#v\nwant %#v", event, tt.res.event) } }) } @@ -203,7 +204,7 @@ func Test_eventstore_RegisterFilterEventMapper(t *testing.T) { func Test_eventData(t *testing.T) { type args struct { - event Event + event EventPusher } type res struct { jsonText []byte @@ -217,11 +218,12 @@ func Test_eventData(t *testing.T) { { name: "data as json bytes", args: args{ - event: &testEvent{ - data: func() interface{} { + event: newTestEvent( + "hodor", + func() interface{} { return []byte(`{"piff":"paff"}`) }, - }, + false), }, res: res{ jsonText: []byte(`{"piff":"paff"}`), @@ -231,11 +233,12 @@ func Test_eventData(t *testing.T) { { name: "data as invalid json bytes", args: args{ - event: &testEvent{ - data: func() interface{} { + event: newTestEvent( + "hodor", + func() interface{} { return []byte(`{"piffpaff"}`) }, - }, + false), }, res: res{ jsonText: []byte(nil), @@ -245,13 +248,14 @@ func Test_eventData(t *testing.T) { { name: "data as struct", args: args{ - event: &testEvent{ - data: func() interface{} { + event: newTestEvent( + "hodor", + func() interface{} { return struct { Piff string `json:"piff"` }{Piff: "paff"} }, - }, + false), }, res: res{ jsonText: []byte(`{"piff":"paff"}`), @@ -261,13 +265,14 @@ func Test_eventData(t *testing.T) { { name: "data as ptr to struct", args: args{ - event: &testEvent{ - data: func() interface{} { + event: newTestEvent( + "hodor", + func() interface{} { return &struct { Piff string `json:"piff"` }{Piff: "paff"} }, - }, + false), }, res: res{ jsonText: []byte(`{"piff":"paff"}`), @@ -277,11 +282,12 @@ func Test_eventData(t *testing.T) { { name: "no data", args: args{ - event: &testEvent{ - data: func() interface{} { + event: newTestEvent( + "hodor", + func() interface{} { return nil }, - }, + false), }, res: res{ jsonText: []byte(nil), @@ -291,11 +297,12 @@ func Test_eventData(t *testing.T) { { name: "invalid because primitive", args: args{ - event: &testEvent{ - data: func() interface{} { + event: newTestEvent( + "hodor", + func() interface{} { return "" }, - }, + false), }, res: res{ jsonText: []byte(nil), @@ -305,12 +312,13 @@ func Test_eventData(t *testing.T) { { name: "invalid because pointer to primitive", args: args{ - event: &testEvent{ - data: func() interface{} { + event: newTestEvent( + "hodor", + func() interface{} { var s string return &s }, - }, + false), }, res: res{ jsonText: []byte(nil), @@ -320,13 +328,14 @@ func Test_eventData(t *testing.T) { { name: "invalid because invalid struct for json", args: args{ - event: &testEvent{ - data: func() interface{} { + event: newTestEvent( + "hodor", + func() interface{} { return struct { Field chan string `json:"field"` }{} }, - }, + false), }, res: res{ jsonText: []byte(nil), @@ -367,11 +376,13 @@ func TestEventstore_aggregatesToEvents(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + false), }, }, }, @@ -399,15 +410,19 @@ func TestEventstore_aggregatesToEvents(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + false), + newTestEvent( + "", + func() interface{} { + return nil + }, + false), }, }, }, @@ -446,11 +461,13 @@ func TestEventstore_aggregatesToEvents(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return `{"data":""` }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return `{"data":""` + }, + false), }, }, }, @@ -465,24 +482,30 @@ func TestEventstore_aggregatesToEvents(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + false), + newTestEvent( + "", + func() interface{} { + return nil + }, + false), }, }, &testAggregate{ id: "2", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: true, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + true), }, }, }, @@ -621,11 +644,13 @@ func TestEventstore_Push(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + false), }, }, }, @@ -660,15 +685,19 @@ func TestEventstore_Push(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + false), + newTestEvent( + "", + func() interface{} { + return nil + }, + false), }, }, }, @@ -717,24 +746,30 @@ func TestEventstore_Push(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + false), + newTestEvent( + "", + func() interface{} { + return nil + }, + false), }, }, &testAggregate{ id: "2", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: true, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + true), }, }, }, @@ -798,11 +833,13 @@ func TestEventstore_Push(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return nil }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return nil + }, + false), }, }, }, @@ -823,11 +860,13 @@ func TestEventstore_Push(t *testing.T) { aggregates: []aggregater{ &testAggregate{ id: "1", - events: []Event{ - &testEvent{ - data: func() interface{} { return `{"data":""` }, - shouldCheckPrevious: false, - }, + events: []EventPusher{ + newTestEvent( + "", + func() interface{} { + return `{"data":""` + }, + false), }, }, }, diff --git a/internal/eventstore/v2/example_test.go b/internal/eventstore/v2/example_test.go index a41806526c..ea85ae5c0d 100644 --- a/internal/eventstore/v2/example_test.go +++ b/internal/eventstore/v2/example_test.go @@ -18,6 +18,8 @@ import ( // ------------------------------------------------------------ type UserAggregate struct { + eventstore.BaseEvent + eventstore.Aggregate FirstName string } @@ -28,8 +30,13 @@ func (a *UserAggregate) ID() string { func (a *UserAggregate) Type() eventstore.AggregateType { return "test.user" } -func (a *UserAggregate) Events() []eventstore.Event { - return a.Aggregate.Events +func (a *UserAggregate) Events() []eventstore.EventPusher { + events := make([]eventstore.EventPusher, len(a.Aggregate.Events)) + for i, event := range a.Aggregate.Events { + events[i] = event + } + + return events } func (a *UserAggregate) ResourceOwner() string { return "caos" @@ -69,14 +76,26 @@ func (rm *UserAggregate) Reduce() error { // ------------------------------------------------------------ type UserAddedEvent struct { + eventstore.BaseEvent `json:"-"` + FirstName string `json:"firstName"` - metaData *eventstore.EventMetaData +} + +func NewUserAddedEvent(firstName string) *UserAddedEvent { + return &UserAddedEvent{ + FirstName: firstName, + BaseEvent: eventstore.BaseEvent{ + Service: "test.suite", + User: "adlerhurst", + EventType: "user.added", + }, + } } func UserAddedEventMapper() (eventstore.EventType, func(*repository.Event) (eventstore.Event, error)) { return "user.added", func(event *repository.Event) (eventstore.Event, error) { e := &UserAddedEvent{ - metaData: eventstore.MetaDataFromRepo(event), + BaseEvent: *eventstore.BaseEventFromRepo(event), } err := json.Unmarshal(event.Data, e) if err != nil { @@ -90,39 +109,35 @@ func (e *UserAddedEvent) CheckPrevious() bool { return true } -func (e *UserAddedEvent) EditorService() string { - return "test.suite" -} - -func (e *UserAddedEvent) EditorUser() string { - return "adlerhurst" -} - -func (e *UserAddedEvent) Type() eventstore.EventType { - return "user.added" -} - func (e *UserAddedEvent) Data() interface{} { return e } -func (e *UserAddedEvent) MetaData() *eventstore.EventMetaData { - return e.metaData -} - // ------------------------------------------------------------ // User first name changed event start // ------------------------------------------------------------ type UserFirstNameChangedEvent struct { - FirstName string `json:"firstName"` - metaData *eventstore.EventMetaData `json:"-"` + eventstore.BaseEvent `json:"-"` + + FirstName string `json:"firstName"` +} + +func NewUserFirstNameChangedEvent(firstName string) *UserFirstNameChangedEvent { + return &UserFirstNameChangedEvent{ + FirstName: firstName, + BaseEvent: eventstore.BaseEvent{ + Service: "test.suite", + User: "adlerhurst", + EventType: "user.firstName.changed", + }, + } } func UserFirstNameChangedMapper() (eventstore.EventType, func(*repository.Event) (eventstore.Event, error)) { return "user.firstName.changed", func(event *repository.Event) (eventstore.Event, error) { e := &UserFirstNameChangedEvent{ - metaData: eventstore.MetaDataFromRepo(event), + BaseEvent: *eventstore.BaseEventFromRepo(event), } err := json.Unmarshal(event.Data, e) if err != nil { @@ -136,38 +151,32 @@ func (e *UserFirstNameChangedEvent) CheckPrevious() bool { return true } -func (e *UserFirstNameChangedEvent) EditorService() string { - return "test.suite" -} - -func (e *UserFirstNameChangedEvent) EditorUser() string { - return "adlerhurst" -} - -func (e *UserFirstNameChangedEvent) Type() eventstore.EventType { - return "user.firstName.changed" -} - func (e *UserFirstNameChangedEvent) Data() interface{} { return e } -func (e *UserFirstNameChangedEvent) MetaData() *eventstore.EventMetaData { - return e.metaData -} - // ------------------------------------------------------------ // User password checked event start // ------------------------------------------------------------ type UserPasswordCheckedEvent struct { - metaData *eventstore.EventMetaData `json:"-"` + eventstore.BaseEvent `json:"-"` +} + +func NewUserPasswordCheckedEvent() *UserPasswordCheckedEvent { + return &UserPasswordCheckedEvent{ + BaseEvent: eventstore.BaseEvent{ + Service: "test.suite", + User: "adlerhurst", + EventType: "user.password.checked", + }, + } } func UserPasswordCheckedMapper() (eventstore.EventType, func(*repository.Event) (eventstore.Event, error)) { return "user.password.checked", func(event *repository.Event) (eventstore.Event, error) { return &UserPasswordCheckedEvent{ - metaData: eventstore.MetaDataFromRepo(event), + BaseEvent: *eventstore.BaseEventFromRepo(event), }, nil } } @@ -176,38 +185,32 @@ func (e *UserPasswordCheckedEvent) CheckPrevious() bool { return false } -func (e *UserPasswordCheckedEvent) EditorService() string { - return "test.suite" -} - -func (e *UserPasswordCheckedEvent) EditorUser() string { - return "adlerhurst" -} - -func (e *UserPasswordCheckedEvent) Type() eventstore.EventType { - return "user.password.checked" -} - func (e *UserPasswordCheckedEvent) Data() interface{} { return nil } -func (e *UserPasswordCheckedEvent) MetaData() *eventstore.EventMetaData { - return e.metaData -} - // ------------------------------------------------------------ // User deleted event // ------------------------------------------------------------ type UserDeletedEvent struct { - metaData *eventstore.EventMetaData `json:"-"` + eventstore.BaseEvent `json:"-"` +} + +func NewUserDeletedEvent() *UserDeletedEvent { + return &UserDeletedEvent{ + BaseEvent: eventstore.BaseEvent{ + Service: "test.suite", + User: "adlerhurst", + EventType: "user.deleted", + }, + } } func UserDeletedMapper() (eventstore.EventType, func(*repository.Event) (eventstore.Event, error)) { return "user.deleted", func(event *repository.Event) (eventstore.Event, error) { return &UserDeletedEvent{ - metaData: eventstore.MetaDataFromRepo(event), + BaseEvent: *eventstore.BaseEventFromRepo(event), }, nil } } @@ -216,26 +219,10 @@ func (e *UserDeletedEvent) CheckPrevious() bool { return false } -func (e *UserDeletedEvent) EditorService() string { - return "test.suite" -} - -func (e *UserDeletedEvent) EditorUser() string { - return "adlerhurst" -} - -func (e *UserDeletedEvent) Type() eventstore.EventType { - return "user.deleted" -} - func (e *UserDeletedEvent) Data() interface{} { return nil } -func (e *UserDeletedEvent) MetaData() *eventstore.EventMetaData { - return e.metaData -} - // ------------------------------------------------------------ // Users read model start // ------------------------------------------------------------ @@ -258,18 +245,18 @@ func (rm *UsersReadModel) AppendEvents(events ...eventstore.Event) (err error) { switch e := event.(type) { case *UserAddedEvent: //insert - user := NewUserReadModel(e.MetaData().AggregateID) + user := NewUserReadModel(e.Base().AggregateID) rm.Users = append(rm.Users, user) err = user.AppendEvents(e) case *UserFirstNameChangedEvent, *UserPasswordCheckedEvent: //update - _, user := rm.userByID(e.MetaData().AggregateID) + _, user := rm.userByID(e.Base().aggregateID) if user == nil { return errors.New("user not found") } err = user.AppendEvents(e) case *UserDeletedEvent: - idx, _ := rm.userByID(e.metaData.AggregateID) + idx, _ := rm.userByID(e.Base().AggregateID) if idx < 0 { return nil } @@ -337,7 +324,7 @@ func (rm *UserReadModel) Reduce() error { rm.FirstName = e.FirstName case *UserPasswordCheckedEvent: rm.pwCheckCount++ - rm.lastPasswordCheck = e.metaData.CreationDate + rm.lastPasswordCheck = e.Base().CreationDate } } rm.ReadModel.Reduce() @@ -356,9 +343,9 @@ func TestUserReadModel(t *testing.T) { RegisterFilterEventMapper(UserDeletedMapper()) events, err := es.PushAggregates(context.Background(), - NewUserAggregate("1").AppendEvents(&UserAddedEvent{FirstName: "hodor"}), - NewUserAggregate("2").AppendEvents(&UserAddedEvent{FirstName: "hodor"}, &UserPasswordCheckedEvent{}, &UserPasswordCheckedEvent{}, &UserFirstNameChangedEvent{FirstName: "ueli"}), - NewUserAggregate("2").AppendEvents(&UserDeletedEvent{}), + NewUserAggregate("1").AppendEvents(NewUserAddedEvent("hodor")), + NewUserAggregate("2").AppendEvents(NewUserAddedEvent("hodor"), NewUserPasswordCheckedEvent(), NewUserPasswordCheckedEvent(), NewUserFirstNameChangedEvent("ueli")), + NewUserAggregate("2").AppendEvents(NewUserDeletedEvent()), ) if err != nil { t.Errorf("unexpected error on push aggregates: %v", err) diff --git a/internal/eventstore/v2/read_model.go b/internal/eventstore/v2/read_model.go index 127f8c1639..51a184df3c 100644 --- a/internal/eventstore/v2/read_model.go +++ b/internal/eventstore/v2/read_model.go @@ -33,10 +33,10 @@ func (rm *ReadModel) Reduce() error { } if rm.CreationDate.IsZero() { - rm.CreationDate = rm.Events[0].MetaData().CreationDate + rm.CreationDate = rm.Events[0].Base().creationDate } - rm.ChangeDate = rm.Events[len(rm.Events)-1].MetaData().CreationDate - rm.ProcessedSequence = rm.Events[len(rm.Events)-1].MetaData().Sequence + rm.ChangeDate = rm.Events[len(rm.Events)-1].Base().creationDate + rm.ProcessedSequence = rm.Events[len(rm.Events)-1].Base().sequence // all events processed and not needed anymore rm.Events = nil rm.Events = []Event{} @@ -69,7 +69,7 @@ func (a *Aggregate) Reduce() error { return nil } - a.PreviousSequence = a.Events[len(a.Events)-1].MetaData().Sequence + a.PreviousSequence = a.Events[len(a.Events)-1].Base().sequence // all events processed and not needed anymore a.Events = nil a.Events = []Event{} diff --git a/internal/v2/repository/iam/aggregate.go b/internal/v2/repository/iam/aggregate.go new file mode 100644 index 0000000000..2843071844 --- /dev/null +++ b/internal/v2/repository/iam/aggregate.go @@ -0,0 +1,36 @@ +package iam + +import "github.com/caos/zitadel/internal/eventstore/v2" + +type Aggregate struct { + eventstore.Aggregate +} + +type Step int8 + +type SetupStepEvent struct { + eventstore.BaseEvent `json:"-"` + + Step Step + //Done if the setup is started earlier + Done bool `json:"-"` +} + +func (e *SetupStepEvent) CheckPrevious() bool { + return e.Type() == "iam.setup.started" +} + +//Type implements event +func (e *SetupStepEvent) Type() eventstore.EventType { + if e.Done { + return "iam.setup.done" + } + return "iam.setup.started" +} + +func (e *SetupStepEvent) Data() interface{} { + return e +} + +type MemberAddedEvent struct { +} diff --git a/internal/v2/repository/member/event_added.go b/internal/v2/repository/member/event_added.go new file mode 100644 index 0000000000..7cceb45035 --- /dev/null +++ b/internal/v2/repository/member/event_added.go @@ -0,0 +1,30 @@ +package member + +import ( + "context" + + "github.com/caos/zitadel/internal/eventstore/v2" +) + +func NewMemberAddedEvent(ctx context.Context, userID string, roles ...string) *MemberAddedEvent { + return &MemberAddedEvent{ + BaseEvent: eventstore.BaseEvent{}, + Roles: roles, + UserID: userID, + } +} + +type MemberAddedEvent struct { + eventstore.BaseEvent `json:"-"` + + Roles []string `json:"roles"` + UserID string `json:"userId"` +} + +func (e *MemberAddedEvent) CheckPrevious() bool { + return true +} + +func (e *MemberAddedEvent) Data() interface{} { + return e +} diff --git a/internal/v2/repository/member/event_removed.go b/internal/v2/repository/member/event_removed.go new file mode 100644 index 0000000000..eb13d27138 --- /dev/null +++ b/internal/v2/repository/member/event_removed.go @@ -0,0 +1,19 @@ +package member + +import ( + "github.com/caos/zitadel/internal/eventstore/v2" +) + +type MemberRemovedEvent struct { + eventstore.BaseEvent `json:"-"` + + UserID string `json:"userId"` +} + +func (e *MemberRemovedEvent) CheckPrevious() bool { + return true +} + +func (e *MemberRemovedEvent) Data() interface{} { + return e +}