package testing import ( "context" "testing" "time" platform2 "github.com/influxdata/influxdb/v2/kit/platform" "github.com/influxdata/influxdb/v2/kit/platform/errors" "github.com/google/go-cmp/cmp" platform "github.com/influxdata/influxdb/v2" "github.com/influxdata/influxdb/v2/mock" ) var onboardCmpOptions = cmp.Options{ cmp.Comparer(func(x, y *platform.OnboardingResults) bool { if x == nil && y == nil { return true } if x != nil && y == nil || y != nil && x == nil { return false } return x.User.Name == y.User.Name && x.User.OAuthID == y.User.OAuthID && x.User.Status == y.User.Status && x.Org.Name == y.Org.Name && x.Org.Description == y.Org.Description && x.Bucket.Type == y.Bucket.Type && x.Bucket.Description == y.Bucket.Description && x.Bucket.RetentionPolicyName == y.Bucket.RetentionPolicyName && x.Bucket.RetentionPeriod == y.Bucket.RetentionPeriod && x.Bucket.Name == y.Bucket.Name && (x.Auth != nil && y.Auth != nil && cmp.Equal(x.Auth.Permissions, y.Auth.Permissions)) // its possible auth wont exist on the basic service level }), } // OnboardingFields will include the IDGenerator, TokenGenerator // and IsOnboarding type OnboardingFields struct { IDGenerator platform2.IDGenerator TokenGenerator platform.TokenGenerator TimeGenerator platform.TimeGenerator IsOnboarding bool } // OnboardInitialUser testing func OnboardInitialUser( init func(OnboardingFields, *testing.T) (platform.OnboardingService, func()), t *testing.T, ) { type args struct { request *platform.OnboardingRequest } type wants struct { errCode string results *platform.OnboardingResults } tests := []struct { name string fields OnboardingFields args args wants wants }{ { name: "denied", fields: OnboardingFields{ IDGenerator: &loopIDGenerator{ s: []string{oneID, twoID, threeID, fourID}, }, TokenGenerator: mock.NewTokenGenerator(oneToken, nil), IsOnboarding: false, }, wants: wants{ errCode: errors.EConflict, }, }, { name: "missing username", fields: OnboardingFields{ IDGenerator: &loopIDGenerator{ s: []string{oneID, twoID, threeID, fourID}, }, TokenGenerator: mock.NewTokenGenerator(oneToken, nil), IsOnboarding: true, }, args: args{ request: &platform.OnboardingRequest{ Org: "org1", Bucket: "bucket1", }, }, wants: wants{ errCode: errors.EUnprocessableEntity, }, }, { name: "missing org", fields: OnboardingFields{ IDGenerator: &loopIDGenerator{ s: []string{oneID, twoID, threeID, fourID}, }, TokenGenerator: mock.NewTokenGenerator(oneToken, nil), IsOnboarding: true, }, args: args{ request: &platform.OnboardingRequest{ User: "admin", Bucket: "bucket1", }, }, wants: wants{ errCode: errors.EUnprocessableEntity, }, }, { name: "missing bucket", fields: OnboardingFields{ IDGenerator: &loopIDGenerator{ s: []string{oneID, twoID, threeID, fourID}, }, TokenGenerator: mock.NewTokenGenerator(oneToken, nil), IsOnboarding: true, }, args: args{ request: &platform.OnboardingRequest{ User: "admin", Org: "org1", }, }, wants: wants{ errCode: errors.EUnprocessableEntity, }, }, { name: "valid onboarding json should create a user, org, bucket, and authorization", fields: OnboardingFields{ IDGenerator: &loopIDGenerator{ s: []string{oneID, twoID, threeID, fourID}, }, TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC)}, TokenGenerator: mock.NewTokenGenerator(oneToken, nil), IsOnboarding: true, }, args: args{ request: &platform.OnboardingRequest{ User: "admin", Org: "org1", Bucket: "bucket1", Password: "password1", RetentionPeriodSeconds: 3600 * 24 * 7, // 1 week }, }, wants: wants{ results: &platform.OnboardingResults{ User: &platform.User{ ID: MustIDBase16(oneID), Name: "admin", Status: platform.Active, }, Org: &platform.Organization{ ID: MustIDBase16(twoID), Name: "org1", CRUDLog: platform.CRUDLog{ CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), }, }, Bucket: &platform.Bucket{ ID: MustIDBase16(threeID), Name: "bucket1", OrgID: MustIDBase16(twoID), RetentionPeriod: time.Hour * 24 * 7, CRUDLog: platform.CRUDLog{ CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), }, }, Auth: &platform.Authorization{ ID: MustIDBase16(fourID), Token: oneToken, Status: platform.Active, UserID: MustIDBase16(oneID), Description: "admin's Token", OrgID: MustIDBase16(twoID), Permissions: platform.OperPermissions(), CRUDLog: platform.CRUDLog{ CreatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), UpdatedAt: time.Date(2006, 5, 4, 1, 2, 3, 0, time.UTC), }, }, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s, done := init(tt.fields, t) defer done() ctx := context.Background() results, err := s.OnboardInitialUser(ctx, tt.args.request) if (err != nil) != (tt.wants.errCode != "") { t.Logf("Error: %v", err) t.Fatalf("expected error code '%s' got '%v'", tt.wants.errCode, err) } if err != nil && tt.wants.errCode != "" { if code := errors.ErrorCode(err); code != tt.wants.errCode { t.Logf("Error: %v", err) t.Fatalf("expected error code to match '%s' got '%v'", tt.wants.errCode, code) } } if diff := cmp.Diff(results, tt.wants.results, onboardCmpOptions); diff != "" { t.Errorf("onboarding results are different -got/+want\ndiff %s", diff) } }) } } const ( oneID = "020f755c3c082000" twoID = "020f755c3c082001" threeID = "020f755c3c082002" fourID = "020f755c3c082003" fiveID = "020f755c3c082004" sixID = "020f755c3c082005" oneToken = "020f755c3c082008" ) type loopIDGenerator struct { s []string p int } func (g *loopIDGenerator) ID() platform2.ID { if g.p == len(g.s) { g.p = 0 } id := MustIDBase16(g.s[g.p]) g.p++ return id }