feat: new user auth api (#1168)

* fix: correct selectors for extended writemodel

* fix: no previous checks in eventstore

* start check previous

* feat: auth user commands

* feat: auth user commands

* feat: auth user commands

* feat: otp

* feat: corrections from pr merge

* feat: webauthn

* feat: comment old webauthn

* feat: refactor user, human, machine

* feat: webauth command side

* feat: command and query side in login

* feat: fix user writemodel append events

* fix: remove creation dates on command side

* fix: remove previous sequence

* previous sequence

* fix: external idps

* Update internal/api/grpc/management/user.go

Co-authored-by: Livio Amstutz <[email protected]>

* Update internal/v2/command/user_human_email.go

Co-authored-by: Livio Amstutz <[email protected]>

* fix: pr changes

* fix: phone verification

Co-authored-by: adlerhurst <[email protected]>
Co-authored-by: Livio Amstutz <[email protected]>
This commit is contained in:
Fabi
2021-01-15 09:32:59 +01:00
committed by GitHub
co-authored by Livio Amstutz adlerhurst
parent e5731b0d3b
commit 959530ddad
74 changed files with 1552 additions and 1517 deletions
+35 -55
View File
@@ -17,7 +17,10 @@ import (
)
const (
crdbInsert = "WITH input_event ( " +
//as soon as stored procedures are possible in crdb
// we could move the code to migrations and coll the procedure
// traking issue: https://github.com/cockroachdb/cockroach/issues/17511
crdbInsert = "WITH data ( " +
" event_type, " +
" aggregate_type, " +
" aggregate_id, " +
@@ -27,47 +30,35 @@ const (
" editor_user, " +
" editor_service, " +
" resource_owner, " +
" previous_sequence, " +
// variables below are calculated
" max_event_seq " +
") AS ( " +
" ( " +
//the following select will return no row if no previous event defined
" SELECT " +
" $1::VARCHAR, " +
" $2::VARCHAR, " +
" $3::VARCHAR, " +
" $4::VARCHAR, " +
" COALESCE($5::TIMESTAMPTZ, NOW()), " +
" $6::JSONB, " +
" $7::VARCHAR, " +
" $8::VARCHAR, " +
" resource_owner, " +
" $10::BIGINT, " +
" MAX(event_sequence) AS max_event_seq " +
" FROM eventstore.events " +
" WHERE " +
" aggregate_type = $2::VARCHAR " +
" AND aggregate_id = $3::VARCHAR " +
" GROUP BY resource_owner " +
" ) UNION (" +
// if no previous event we use the given data
" VALUES (" +
" $1::VARCHAR, " +
" $2::VARCHAR, " +
" $3::VARCHAR, " +
" $4::VARCHAR, " +
" COALESCE($5::TIMESTAMPTZ, NOW()), " +
" $6::JSONB, " +
" $7::VARCHAR, " +
" $8::VARCHAR, " +
" $9::VARCHAR, " +
" $10::BIGINT, " +
" NULL::BIGINT " +
" ) " +
" ) " +
// ensure only 1 row in input_event
" LIMIT 1 " +
" previous_sequence" +
") AS (" +
//previous_data selects the needed data of the latest event of the aggregate
// and buffers it (crdb inmemory)
" WITH previous_data AS (" +
" SELECT MAX(event_sequence) AS seq, resource_owner " +
" FROM eventstore.events " +
//TODO: remove LIMIT 1 as soon as data cleaned up (only 1 resource_owner per aggregate)
" WHERE aggregate_type = $2 AND aggregate_id = $3 GROUP BY resource_owner LIMIT 1" +
" )" +
// defines the data to be inserted
" SELECT " +
" $1::VARCHAR AS event_type, " +
" $2::VARCHAR AS aggregate_type, " +
" $3::VARCHAR AS aggregate_id, " +
" $4::VARCHAR AS aggregate_version, " +
" NOW() AS creation_date, " +
" $5::JSONB AS event_data, " +
" $6::VARCHAR AS editor_user, " +
" $7::VARCHAR AS editor_service, " +
" CASE WHEN EXISTS (SELECT * FROM previous_data) " +
" THEN (SELECT resource_owner FROM previous_data) " +
" ELSE $8::VARCHAR " +
" end AS resource_owner, " +
" CASE WHEN EXISTS (SELECT * FROM previous_data) " +
" THEN (SELECT seq FROM previous_data) " +
" ELSE NULL " +
" end AS previous_sequence" +
") " +
"INSERT INTO eventstore.events " +
" ( " +
@@ -94,9 +85,9 @@ const (
" editor_service, " +
" resource_owner, " +
" previous_sequence " +
" FROM input_event " +
" FROM data " +
" ) " +
"RETURNING id, event_sequence, previous_sequence, creation_date, resource_owner "
"RETURNING id, event_sequence, previous_sequence, creation_date, resource_owner"
)
type CRDB struct {
@@ -119,28 +110,17 @@ func (db *CRDB) Push(ctx context.Context, events ...*repository.Event) error {
return caos_errs.ThrowInternal(err, "SQL-OdXRE", "prepare failed")
}
var previousSequence Sequence
for _, event := range events {
previousSequence := Sequence(event.PreviousSequence)
if event.PreviousEvent != nil {
if event.PreviousEvent.AggregateType != event.AggregateType || event.PreviousEvent.AggregateID != event.AggregateID {
return caos_errs.ThrowPreconditionFailed(nil, "SQL-J55uR", "aggregate of linked events unequal")
}
previousSequence = Sequence(event.PreviousEvent.Sequence)
}
err = stmt.QueryRowContext(ctx,
event.Type,
event.AggregateType,
event.AggregateID,
event.Version,
&sql.NullTime{
Time: event.CreationDate,
Valid: !event.CreationDate.IsZero(),
},
Data(event.Data),
event.EditorUser,
event.EditorService,
event.ResourceOwner,
previousSequence,
).Scan(&event.ID, &event.Sequence, &previousSequence, &event.CreationDate, &event.ResourceOwner)
event.PreviousSequence = uint64(previousSequence)
+152 -349
View File
@@ -284,11 +284,11 @@ func TestCRDB_Push_OneAggregate(t *testing.T) {
res res
}{
{
name: "push 1 event with check previous",
name: "push 1 event",
args: args{
ctx: context.Background(),
events: []*repository.Event{
generateEvent(t, "1", true, 0),
generateEvent(t, "1"),
},
},
res: res{
@@ -300,83 +300,14 @@ func TestCRDB_Push_OneAggregate(t *testing.T) {
}},
},
{
name: "fail push 1 event with check previous wrong sequence",
name: "push two events on agg",
args: args{
ctx: context.Background(),
events: []*repository.Event{
generateEvent(t, "2", true, 5),
generateEvent(t, "6"),
generateEvent(t, "6"),
},
},
res: res{
wantErr: true,
eventsRes: eventsRes{
pushedEventsCount: 0,
aggID: []string{"2"},
aggType: repository.AggregateType(t.Name()),
},
},
},
{
name: "push 1 event without check previous",
args: args{
ctx: context.Background(),
events: []*repository.Event{
generateEvent(t, "3", false, 0),
},
},
res: res{
wantErr: false,
eventsRes: eventsRes{
pushedEventsCount: 1,
aggID: []string{"3"},
aggType: repository.AggregateType(t.Name()),
},
},
},
{
name: "push 1 event without check previous wrong sequence",
args: args{
ctx: context.Background(),
events: []*repository.Event{
generateEvent(t, "4", false, 5),
},
},
res: res{
wantErr: false,
eventsRes: eventsRes{
pushedEventsCount: 1,
aggID: []string{"4"},
aggType: repository.AggregateType(t.Name()),
},
},
},
{
name: "fail on push two events on agg without linking",
args: args{
ctx: context.Background(),
events: []*repository.Event{
generateEvent(t, "5", true, 0),
generateEvent(t, "5", true, 0),
},
},
res: res{
wantErr: true,
eventsRes: eventsRes{
pushedEventsCount: 0,
aggID: []string{"5"},
aggType: repository.AggregateType(t.Name()),
},
},
},
{
name: "push two events on agg with linking",
args: args{
ctx: context.Background(),
events: linkEvents(
generateEvent(t, "6", true, 0),
generateEvent(t, "6", true, 0),
),
},
res: res{
wantErr: false,
eventsRes: eventsRes{
@@ -386,51 +317,12 @@ func TestCRDB_Push_OneAggregate(t *testing.T) {
},
},
},
{
name: "push two events on agg with linking without check previous",
args: args{
ctx: context.Background(),
events: linkEvents(
generateEvent(t, "7", false, 0),
generateEvent(t, "7", false, 0),
),
},
res: res{
wantErr: false,
eventsRes: eventsRes{
pushedEventsCount: 2,
aggID: []string{"7"},
aggType: repository.AggregateType(t.Name()),
},
},
},
{
name: "push two events on agg with linking mixed check previous",
args: args{
ctx: context.Background(),
events: linkEvents(
generateEvent(t, "8", false, 0),
generateEvent(t, "8", true, 0),
generateEvent(t, "8", false, 0),
generateEvent(t, "8", true, 0),
generateEvent(t, "8", true, 0),
),
},
res: res{
wantErr: false,
eventsRes: eventsRes{
pushedEventsCount: 5,
aggID: []string{"8"},
aggType: repository.AggregateType(t.Name()),
},
},
},
{
name: "failed push because context canceled",
args: args{
ctx: canceledCtx(),
events: []*repository.Event{
generateEvent(t, "9", true, 0),
generateEvent(t, "9"),
},
},
res: res{
@@ -485,11 +377,11 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) {
res res
}{
{
name: "push two aggregates both check previous",
name: "push two aggregates",
args: args{
events: []*repository.Event{
generateEvent(t, "100", true, 0),
generateEvent(t, "101", true, 0),
generateEvent(t, "100"),
generateEvent(t, "101"),
},
},
res: res{
@@ -502,18 +394,14 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) {
},
},
{
name: "push two aggregates both check previous multiple events",
name: "push two aggregates both multiple events",
args: args{
events: combineEventLists(
linkEvents(
generateEvent(t, "102", true, 0),
generateEvent(t, "102", true, 0),
),
linkEvents(
generateEvent(t, "103", true, 0),
generateEvent(t, "103", true, 0),
),
),
events: []*repository.Event{
generateEvent(t, "102"),
generateEvent(t, "102"),
generateEvent(t, "103"),
generateEvent(t, "103"),
},
},
res: res{
wantErr: false,
@@ -525,64 +413,28 @@ func TestCRDB_Push_MultipleAggregate(t *testing.T) {
},
},
{
name: "fail push linked events of different aggregates",
name: "push two aggregates mixed multiple events",
args: args{
events: linkEvents(
generateEvent(t, "104", false, 0),
generateEvent(t, "105", false, 0),
),
},
res: res{
wantErr: true,
eventsRes: eventsRes{
pushedEventsCount: 0,
aggID: []string{"104", "105"},
aggType: []repository.AggregateType{repository.AggregateType(t.Name())},
events: []*repository.Event{
generateEvent(t, "106"),
generateEvent(t, "106"),
generateEvent(t, "106"),
generateEvent(t, "106"),
generateEvent(t, "107"),
generateEvent(t, "107"),
generateEvent(t, "107"),
generateEvent(t, "107"),
generateEvent(t, "108"),
generateEvent(t, "108"),
generateEvent(t, "108"),
generateEvent(t, "108"),
},
},
},
{
name: "push two aggregates mixed check previous multiple events",
args: args{
events: combineEventLists(
linkEvents(
generateEvent(t, "106", true, 0),
generateEvent(t, "106", false, 0),
generateEvent(t, "106", false, 0),
generateEvent(t, "106", true, 0),
),
linkEvents(
generateEvent(t, "107", false, 0),
generateEvent(t, "107", true, 0),
generateEvent(t, "107", false, 0),
generateEvent(t, "107", true, 0),
),
linkEvents(
generateEvent(t, "108", true, 0),
generateEvent(t, "108", false, 0),
generateEvent(t, "108", false, 0),
generateEvent(t, "108", true, 0),
),
),
},
},
{
name: "failed push same aggregate in two transactions",
args: args{
events: combineEventLists(
linkEvents(
generateEvent(t, "109", true, 0),
),
linkEvents(
generateEvent(t, "109", true, 0),
),
),
},
res: res{
wantErr: true,
wantErr: false,
eventsRes: eventsRes{
pushedEventsCount: 0,
aggID: []string{"109"},
pushedEventsCount: 12,
aggID: []string{"106", "107", "108"},
aggType: []repository.AggregateType{repository.AggregateType(t.Name())},
},
},
@@ -633,25 +485,19 @@ func TestCRDB_Push_Parallel(t *testing.T) {
name: "clients push different aggregates",
args: args{
events: [][]*repository.Event{
linkEvents(
generateEvent(t, "200", false, 0),
generateEvent(t, "200", true, 0),
generateEvent(t, "200", false, 0),
),
linkEvents(
generateEvent(t, "201", false, 0),
generateEvent(t, "201", true, 0),
generateEvent(t, "201", false, 0),
),
combineEventLists(
linkEvents(
generateEvent(t, "202", false, 0),
),
linkEvents(
generateEvent(t, "203", true, 0),
generateEvent(t, "203", false, 0),
),
),
{
generateEvent(t, "200"),
generateEvent(t, "200"),
generateEvent(t, "200"),
generateEvent(t, "201"),
generateEvent(t, "201"),
generateEvent(t, "201"),
},
{
generateEvent(t, "202"),
generateEvent(t, "203"),
generateEvent(t, "203"),
},
},
},
res: res{
@@ -664,41 +510,31 @@ func TestCRDB_Push_Parallel(t *testing.T) {
},
},
{
name: "clients push same aggregates no check previous",
name: "clients push same aggregates",
args: args{
events: [][]*repository.Event{
linkEvents(
generateEvent(t, "204", false, 0),
generateEvent(t, "204", false, 0),
),
linkEvents(
generateEvent(t, "204", false, 0),
generateEvent(t, "204", false, 0),
),
combineEventLists(
linkEvents(
generateEvent(t, "205", false, 0),
generateEvent(t, "205", false, 0),
generateEvent(t, "205", false, 0),
),
linkEvents(
generateEvent(t, "206", false, 0),
generateEvent(t, "206", false, 0),
generateEvent(t, "206", false, 0),
),
),
combineEventLists(
linkEvents(
generateEvent(t, "204", false, 0),
),
linkEvents(
generateEvent(t, "205", false, 0),
generateEvent(t, "205", false, 0),
),
linkEvents(
generateEvent(t, "206", false, 0),
),
),
{
generateEvent(t, "204"),
generateEvent(t, "204"),
},
{
generateEvent(t, "204"),
generateEvent(t, "204"),
},
{
generateEvent(t, "205"),
generateEvent(t, "205"),
generateEvent(t, "205"),
generateEvent(t, "206"),
generateEvent(t, "206"),
generateEvent(t, "206"),
},
{
generateEvent(t, "204"),
generateEvent(t, "205"),
generateEvent(t, "205"),
generateEvent(t, "206"),
},
},
},
res: res{
@@ -711,24 +547,24 @@ func TestCRDB_Push_Parallel(t *testing.T) {
},
},
{
name: "clients push different aggregates one with check previous",
name: "clients push different aggregates",
args: args{
events: [][]*repository.Event{
linkEvents(
generateEvent(t, "207", false, 0),
generateEvent(t, "207", false, 0),
generateEvent(t, "207", false, 0),
generateEvent(t, "207", false, 0),
generateEvent(t, "207", false, 0),
generateEvent(t, "207", false, 0),
),
linkEvents(
generateEvent(t, "208", true, 0),
generateEvent(t, "208", true, 0),
generateEvent(t, "208", true, 0),
generateEvent(t, "208", true, 0),
generateEvent(t, "208", true, 0),
),
{
generateEvent(t, "207"),
generateEvent(t, "207"),
generateEvent(t, "207"),
generateEvent(t, "207"),
generateEvent(t, "207"),
generateEvent(t, "207"),
},
{
generateEvent(t, "208"),
generateEvent(t, "208"),
generateEvent(t, "208"),
generateEvent(t, "208"),
generateEvent(t, "208"),
},
},
},
res: res{
@@ -741,21 +577,21 @@ func TestCRDB_Push_Parallel(t *testing.T) {
},
},
{
name: "clients push different aggregates all with check previous on first event fail",
name: "clients push same aggregates",
args: args{
events: [][]*repository.Event{
linkEvents(
generateEventWithData(t, "210", true, 0, []byte(`{ "transaction": 1 }`)),
generateEventWithData(t, "210", false, 0, []byte(`{ "transaction": 1.1 }`)),
),
linkEvents(
generateEventWithData(t, "210", true, 0, []byte(`{ "transaction": 2 }`)),
generateEventWithData(t, "210", false, 0, []byte(`{ "transaction": 2.1 }`)),
),
linkEvents(
generateEventWithData(t, "210", true, 0, []byte(`{ "transaction": 3 }`)),
generateEventWithData(t, "210", false, 0, []byte(`{ "transaction": 30.1 }`)),
),
{
generateEventWithData(t, "210", []byte(`{ "transaction": 1 }`)),
generateEventWithData(t, "210", []byte(`{ "transaction": 1.1 }`)),
},
{
generateEventWithData(t, "210", []byte(`{ "transaction": 2 }`)),
generateEventWithData(t, "210", []byte(`{ "transaction": 2.1 }`)),
},
{
generateEventWithData(t, "210", []byte(`{ "transaction": 3 }`)),
generateEventWithData(t, "210", []byte(`{ "transaction": 30.1 }`)),
},
},
},
res: res{
@@ -850,9 +686,9 @@ func TestCRDB_Filter(t *testing.T) {
},
fields: fields{
existingEvents: []*repository.Event{
generateEvent(t, "300", false, 0),
generateEvent(t, "300", false, 0),
generateEvent(t, "300", false, 0),
generateEvent(t, "300"),
generateEvent(t, "300"),
generateEvent(t, "300"),
},
},
res: res{
@@ -873,10 +709,10 @@ func TestCRDB_Filter(t *testing.T) {
},
fields: fields{
existingEvents: []*repository.Event{
generateEvent(t, "303", false, 0),
generateEvent(t, "303", false, 0),
generateEvent(t, "303", false, 0),
generateEvent(t, "305", false, 0),
generateEvent(t, "303"),
generateEvent(t, "303"),
generateEvent(t, "303"),
generateEvent(t, "305"),
},
},
res: res{
@@ -938,9 +774,9 @@ func TestCRDB_LatestSequence(t *testing.T) {
},
fields: fields{
existingEvents: []*repository.Event{
generateEvent(t, "400", false, 0),
generateEvent(t, "400", false, 0),
generateEvent(t, "400", false, 0),
generateEvent(t, "400"),
generateEvent(t, "400"),
generateEvent(t, "400"),
},
},
res: res{
@@ -960,9 +796,9 @@ func TestCRDB_LatestSequence(t *testing.T) {
},
fields: fields{
existingEvents: []*repository.Event{
generateEvent(t, "401", false, 0),
generateEvent(t, "401", false, 0),
generateEvent(t, "401", false, 0),
generateEvent(t, "401"),
generateEvent(t, "401"),
generateEvent(t, "401"),
},
},
res: res{
@@ -1016,8 +852,8 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) {
name: "two events of same aggregate same resource owner",
args: args{
events: []*repository.Event{
generateEvent(t, "500", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "500", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "500", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "500", func(e *repository.Event) { e.ResourceOwner = "caos" }),
},
},
fields: fields{
@@ -1032,8 +868,8 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) {
name: "two events of different aggregate same resource owner",
args: args{
events: []*repository.Event{
generateEvent(t, "501", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "502", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "501", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "502", func(e *repository.Event) { e.ResourceOwner = "caos" }),
},
},
fields: fields{
@@ -1048,8 +884,8 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) {
name: "two events of different aggregate different resource owner",
args: args{
events: []*repository.Event{
generateEvent(t, "503", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "504", false, 0, func(e *repository.Event) { e.ResourceOwner = "zitadel" }),
generateEvent(t, "503", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "504", func(e *repository.Event) { e.ResourceOwner = "zitadel" }),
},
},
fields: fields{
@@ -1063,16 +899,12 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) {
{
name: "events of different aggregate different resource owner",
args: args{
events: combineEventLists(
linkEvents(
generateEvent(t, "505", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "505", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
),
linkEvents(
generateEvent(t, "506", false, 0, func(e *repository.Event) { e.ResourceOwner = "zitadel" }),
generateEvent(t, "506", false, 0, func(e *repository.Event) { e.ResourceOwner = "zitadel" }),
),
),
events: []*repository.Event{
generateEvent(t, "505", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "505", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "506", func(e *repository.Event) { e.ResourceOwner = "zitadel" }),
generateEvent(t, "506", func(e *repository.Event) { e.ResourceOwner = "zitadel" }),
},
},
fields: fields{
aggregateIDs: []string{"505", "506"},
@@ -1085,16 +917,12 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) {
{
name: "events of different aggregate different resource owner per event",
args: args{
events: combineEventLists(
linkEvents(
generateEvent(t, "507", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "507", false, 0, func(e *repository.Event) { e.ResourceOwner = "ignored" }),
),
linkEvents(
generateEvent(t, "508", false, 0, func(e *repository.Event) { e.ResourceOwner = "zitadel" }),
generateEvent(t, "508", false, 0, func(e *repository.Event) { e.ResourceOwner = "ignored" }),
),
),
events: []*repository.Event{
generateEvent(t, "507", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "507", func(e *repository.Event) { e.ResourceOwner = "ignored" }),
generateEvent(t, "508", func(e *repository.Event) { e.ResourceOwner = "zitadel" }),
generateEvent(t, "508", func(e *repository.Event) { e.ResourceOwner = "ignored" }),
},
},
fields: fields{
aggregateIDs: []string{"507", "508"},
@@ -1107,16 +935,12 @@ func TestCRDB_Push_ResourceOwner(t *testing.T) {
{
name: "events of one aggregate different resource owner per event",
args: args{
events: combineEventLists(
linkEvents(
generateEvent(t, "509", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "509", false, 0, func(e *repository.Event) { e.ResourceOwner = "ignored" }),
),
linkEvents(
generateEvent(t, "509", false, 0, func(e *repository.Event) { e.ResourceOwner = "ignored" }),
generateEvent(t, "509", false, 0, func(e *repository.Event) { e.ResourceOwner = "ignored" }),
),
),
events: []*repository.Event{
generateEvent(t, "509", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "509", func(e *repository.Event) { e.ResourceOwner = "ignored" }),
generateEvent(t, "509", func(e *repository.Event) { e.ResourceOwner = "ignored" }),
generateEvent(t, "509", func(e *repository.Event) { e.ResourceOwner = "ignored" }),
},
},
fields: fields{
aggregateIDs: []string{"509"},
@@ -1180,34 +1004,16 @@ func canceledCtx() context.Context {
return ctx
}
func combineEventLists(lists ...[]*repository.Event) []*repository.Event {
combined := make([]*repository.Event, 0)
for _, list := range lists {
combined = append(combined, list...)
}
return combined
}
func linkEvents(events ...*repository.Event) []*repository.Event {
for i := 1; i < len(events); i++ {
events[i].PreviousEvent = events[i-1]
}
return events
}
func generateEvent(t *testing.T, aggregateID string, checkPrevious bool, previousSeq uint64, opts ...func(*repository.Event)) *repository.Event {
func generateEvent(t *testing.T, aggregateID string, opts ...func(*repository.Event)) *repository.Event {
t.Helper()
e := &repository.Event{
AggregateID: aggregateID,
AggregateType: repository.AggregateType(t.Name()),
CheckPreviousSequence: checkPrevious,
EditorService: "svc",
EditorUser: "user",
PreviousEvent: nil,
PreviousSequence: previousSeq,
ResourceOwner: "ro",
Type: "test.created",
Version: "v1",
AggregateID: aggregateID,
AggregateType: repository.AggregateType(t.Name()),
EditorService: "svc",
EditorUser: "user",
ResourceOwner: "ro",
Type: "test.created",
Version: "v1",
}
for _, opt := range opts {
@@ -1217,19 +1023,16 @@ func generateEvent(t *testing.T, aggregateID string, checkPrevious bool, previou
return e
}
func generateEventWithData(t *testing.T, aggregateID string, checkPrevious bool, previousSeq uint64, data []byte) *repository.Event {
func generateEventWithData(t *testing.T, aggregateID string, data []byte) *repository.Event {
t.Helper()
return &repository.Event{
AggregateID: aggregateID,
AggregateType: repository.AggregateType(t.Name()),
CheckPreviousSequence: checkPrevious,
EditorService: "svc",
EditorUser: "user",
PreviousEvent: nil,
PreviousSequence: previousSeq,
ResourceOwner: "ro",
Type: "test.created",
Version: "v1",
Data: data,
AggregateID: aggregateID,
AggregateType: repository.AggregateType(t.Name()),
EditorService: "svc",
EditorUser: "user",
ResourceOwner: "ro",
Type: "test.created",
Version: "v1",
Data: data,
}
}
@@ -27,9 +27,13 @@ func TestMain(m *testing.M) {
}
testCRDBClient, err = sql.Open("postgres", ts.PGURL().String())
if err != nil {
logging.LogWithFields("REPOS-CF6dQ", "error", err).Fatal("unable to connect to db")
}
if err = testCRDBClient.Ping(); err != nil {
logging.LogWithFields("REPOS-CF6dQ", "error", err).Fatal("unable to ping db")
}
defer func() {
testCRDBClient.Close()
@@ -112,12 +112,11 @@ func eventsScanner(scanner scan, dest interface{}) (err error) {
)
if err != nil {
logging.Log("SQL-kn1Sw").WithError(err).Warn("unable to scan row")
return z_errors.ThrowInternal(err, "SQL-J0hFS", "unable to scan row")
logging.Log("SQL-3mofs").WithError(err).Warn("unable to scan row")
return z_errors.ThrowInternal(err, "SQL-M0dsf", "unable to scan row")
}
event.PreviousSequence = uint64(previousSequence)
event.Data = make([]byte, len(data))
copy(event.Data, data)
@@ -329,9 +329,9 @@ func Test_query_events_with_crdb(t *testing.T) {
fields: fields{
client: testCRDBClient,
existingEvents: []*repository.Event{
generateEvent(t, "300", false, 0),
generateEvent(t, "300", false, 0),
generateEvent(t, "300", false, 0),
generateEvent(t, "300"),
generateEvent(t, "300"),
generateEvent(t, "300"),
},
},
res: res{
@@ -352,10 +352,10 @@ func Test_query_events_with_crdb(t *testing.T) {
fields: fields{
client: testCRDBClient,
existingEvents: []*repository.Event{
generateEvent(t, "301", false, 0),
generateEvent(t, "302", false, 0),
generateEvent(t, "302", false, 0),
generateEvent(t, "303", false, 0, func(e *repository.Event) { e.AggregateType = "not in list" }),
generateEvent(t, "301"),
generateEvent(t, "302"),
generateEvent(t, "302"),
generateEvent(t, "303", func(e *repository.Event) { e.AggregateType = "not in list" }),
},
},
res: res{
@@ -377,11 +377,11 @@ func Test_query_events_with_crdb(t *testing.T) {
fields: fields{
client: testCRDBClient,
existingEvents: []*repository.Event{
generateEvent(t, "303", false, 0),
generateEvent(t, "303", false, 0),
generateEvent(t, "303", false, 0),
generateEvent(t, "304", false, 0, func(e *repository.Event) { e.AggregateType = "not in list" }),
generateEvent(t, "305", false, 0),
generateEvent(t, "303"),
generateEvent(t, "303"),
generateEvent(t, "303"),
generateEvent(t, "304", func(e *repository.Event) { e.AggregateType = "not in list" }),
generateEvent(t, "305"),
},
},
res: res{
@@ -402,11 +402,11 @@ func Test_query_events_with_crdb(t *testing.T) {
fields: fields{
client: testCRDBClient,
existingEvents: []*repository.Event{
generateEvent(t, "306", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "307", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "308", false, 0, func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "309", false, 0, func(e *repository.Event) { e.ResourceOwner = "orgID" }),
generateEvent(t, "309", false, 0, func(e *repository.Event) { e.ResourceOwner = "orgID" }),
generateEvent(t, "306", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "307", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "308", func(e *repository.Event) { e.ResourceOwner = "caos" }),
generateEvent(t, "309", func(e *repository.Event) { e.ResourceOwner = "orgID" }),
generateEvent(t, "309", func(e *repository.Event) { e.ResourceOwner = "orgID" }),
},
},
res: res{
@@ -428,11 +428,11 @@ func Test_query_events_with_crdb(t *testing.T) {
fields: fields{
client: testCRDBClient,
existingEvents: []*repository.Event{
generateEvent(t, "307", false, 0, func(e *repository.Event) { e.EditorService = "MANAGEMENT-API" }),
generateEvent(t, "307", false, 0, func(e *repository.Event) { e.EditorService = "MANAGEMENT-API" }),
generateEvent(t, "308", false, 0, func(e *repository.Event) { e.EditorService = "ADMIN-API" }),
generateEvent(t, "309", false, 0, func(e *repository.Event) { e.EditorService = "AUTHAPI" }),
generateEvent(t, "309", false, 0, func(e *repository.Event) { e.EditorService = "AUTHAPI" }),
generateEvent(t, "307", func(e *repository.Event) { e.EditorService = "MANAGEMENT-API" }),
generateEvent(t, "307", func(e *repository.Event) { e.EditorService = "MANAGEMENT-API" }),
generateEvent(t, "308", func(e *repository.Event) { e.EditorService = "ADMIN-API" }),
generateEvent(t, "309", func(e *repository.Event) { e.EditorService = "AUTHAPI" }),
generateEvent(t, "309", func(e *repository.Event) { e.EditorService = "AUTHAPI" }),
},
},
res: res{
@@ -455,13 +455,13 @@ func Test_query_events_with_crdb(t *testing.T) {
fields: fields{
client: testCRDBClient,
existingEvents: []*repository.Event{
generateEvent(t, "310", false, 0, func(e *repository.Event) { e.EditorUser = "adlerhurst" }),
generateEvent(t, "310", false, 0, func(e *repository.Event) { e.EditorUser = "adlerhurst" }),
generateEvent(t, "310", false, 0, func(e *repository.Event) { e.EditorUser = "nobody" }),
generateEvent(t, "311", false, 0, func(e *repository.Event) { e.EditorUser = "" }),
generateEvent(t, "311", false, 0, func(e *repository.Event) { e.EditorUser = "" }),
generateEvent(t, "312", false, 0, func(e *repository.Event) { e.EditorUser = "fforootd" }),
generateEvent(t, "312", false, 0, func(e *repository.Event) { e.EditorUser = "fforootd" }),
generateEvent(t, "310", func(e *repository.Event) { e.EditorUser = "adlerhurst" }),
generateEvent(t, "310", func(e *repository.Event) { e.EditorUser = "adlerhurst" }),
generateEvent(t, "310", func(e *repository.Event) { e.EditorUser = "nobody" }),
generateEvent(t, "311", func(e *repository.Event) { e.EditorUser = "" }),
generateEvent(t, "311", func(e *repository.Event) { e.EditorUser = "" }),
generateEvent(t, "312", func(e *repository.Event) { e.EditorUser = "fforootd" }),
generateEvent(t, "312", func(e *repository.Event) { e.EditorUser = "fforootd" }),
},
},
res: res{
@@ -483,15 +483,15 @@ func Test_query_events_with_crdb(t *testing.T) {
fields: fields{
client: testCRDBClient,
existingEvents: []*repository.Event{
generateEvent(t, "311", false, 0, func(e *repository.Event) { e.Type = "user.created" }),
generateEvent(t, "311", false, 0, func(e *repository.Event) { e.Type = "user.updated" }),
generateEvent(t, "311", false, 0, func(e *repository.Event) { e.Type = "user.deactivated" }),
generateEvent(t, "311", false, 0, func(e *repository.Event) { e.Type = "user.locked" }),
generateEvent(t, "312", false, 0, func(e *repository.Event) { e.Type = "user.created" }),
generateEvent(t, "312", false, 0, func(e *repository.Event) { e.Type = "user.updated" }),
generateEvent(t, "312", false, 0, func(e *repository.Event) { e.Type = "user.deactivated" }),
generateEvent(t, "312", false, 0, func(e *repository.Event) { e.Type = "user.reactivated" }),
generateEvent(t, "313", false, 0, func(e *repository.Event) { e.Type = "user.locked" }),
generateEvent(t, "311", func(e *repository.Event) { e.Type = "user.created" }),
generateEvent(t, "311", func(e *repository.Event) { e.Type = "user.updated" }),
generateEvent(t, "311", func(e *repository.Event) { e.Type = "user.deactivated" }),
generateEvent(t, "311", func(e *repository.Event) { e.Type = "user.locked" }),
generateEvent(t, "312", func(e *repository.Event) { e.Type = "user.created" }),
generateEvent(t, "312", func(e *repository.Event) { e.Type = "user.updated" }),
generateEvent(t, "312", func(e *repository.Event) { e.Type = "user.deactivated" }),
generateEvent(t, "312", func(e *repository.Event) { e.Type = "user.reactivated" }),
generateEvent(t, "313", func(e *repository.Event) { e.Type = "user.locked" }),
},
},
res: res{