diff --git a/.mockery.yml b/.mockery.yml index 2c02590d6a..95acc7ce3e 100644 --- a/.mockery.yml +++ b/.mockery.yml @@ -28,7 +28,8 @@ packages: github.com/nucleuscloud/neosync/backend/internal/temporal/client-manager: interfaces: DB: - TemporalClientManagerClient: + # this is broken. it uses the wrong package. after running mockery change internal to client in mock + # TemporalClientManagerClient: github.com/nucleuscloud/neosync/worker/gen/go/db/postgresql: # config: interfaces: diff --git a/backend/internal/nucleusdb/jobs_test.go b/backend/internal/nucleusdb/jobs_test.go new file mode 100644 index 0000000000..90905c08d9 --- /dev/null +++ b/backend/internal/nucleusdb/jobs_test.go @@ -0,0 +1,132 @@ +package nucleusdb + +import ( + "context" + "errors" + "testing" + + db_queries "github.com/nucleuscloud/neosync/backend/gen/go/db" + mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1" + pg_models "github.com/nucleuscloud/neosync/backend/sql/postgresql/models" + "github.com/zeebo/assert" +) + +const ( + mockJobId = "9e9ec62a-e0f8-4f0b-bf04-7de327ab6f9c" + mockConnId = "8e34ce5b-cde8-4fc5-bd0a-7d1e50a4b14f" +) + +// CreateJob +func Test_CreateJob(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + jobUuid, _ := ToUuid(mockJobId) + accountUuid, _ := ToUuid(mockAccountId) + connUuid, _ := ToUuid(mockConnId) + ctx := context.Background() + createJobParams := &db_queries.CreateJobParams{ + Name: "job-name", + AccountID: accountUuid, + } + destinations := []*CreateJobConnectionDestination{ + {ConnectionId: connUuid, Options: &pg_models.JobDestinationOptions{}}, + } + destinationParams := []db_queries.CreateJobConnectionDestinationsParams{ + {JobID: jobUuid, ConnectionID: connUuid, Options: &pg_models.JobDestinationOptions{}}, + } + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("CreateJob", ctx, mockTx, *createJobParams).Return(db_queries.NeosyncApiJob{ID: jobUuid}, nil) + querierMock.On("CreateJobConnectionDestinations", ctx, mockTx, destinationParams).Return(int64(1), nil) + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.CreateJob(context.Background(), createJobParams, destinations) + + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, jobUuid, resp.ID) +} + +func Test_CreateJob_Rollback(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + jobUuid, _ := ToUuid(mockJobId) + accountUuid, _ := ToUuid(mockAccountId) + connUuid, _ := ToUuid(mockConnId) + ctx := context.Background() + createJobParams := &db_queries.CreateJobParams{ + Name: "job-name", + AccountID: accountUuid, + } + destinations := []*CreateJobConnectionDestination{ + {ConnectionId: connUuid, Options: &pg_models.JobDestinationOptions{}}, + } + destinationParams := []db_queries.CreateJobConnectionDestinationsParams{ + {JobID: jobUuid, ConnectionID: connUuid, Options: &pg_models.JobDestinationOptions{}}, + } + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("CreateJob", ctx, mockTx, *createJobParams).Return(db_queries.NeosyncApiJob{ID: jobUuid}, nil) + querierMock.On("CreateJobConnectionDestinations", ctx, mockTx, destinationParams).Return(int64(1), errors.New("error")) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.CreateJob(context.Background(), createJobParams, destinations) + + mockTx.AssertNotCalled(t, "Commit", ctx) + assert.Error(t, err) + assert.Nil(t, resp) +} + +// SetSqlSourceSubsets +func Test_SetSqlSourceSubsets(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + jobUuid, _ := ToUuid(mockJobId) + userUuid, _ := ToUuid(mockUserId) + connUuid, _ := ToUuid(mockConnId) + ctx := context.Background() + whereClause := "where" + schemas := &mgmtv1alpha1.JobSourceSqlSubetSchemas{ + Schemas: &mgmtv1alpha1.JobSourceSqlSubetSchemas_PostgresSubset{ + PostgresSubset: &mgmtv1alpha1.PostgresSourceSchemaSubset{ + PostgresSchemas: []*mgmtv1alpha1.PostgresSourceSchemaOption{ + {Schema: "schema", Tables: []*mgmtv1alpha1.PostgresSourceTableOption{{Table: "table-1", WhereClause: &whereClause}}}, + }, + }, + }, + } + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetJobById", ctx, mockTx, jobUuid).Return(db_queries.NeosyncApiJob{ID: jobUuid, ConnectionSourceID: connUuid, ConnectionOptions: &pg_models.JobSourceOptions{}}, nil) + querierMock.On("UpdateJobSource", ctx, mockTx, db_queries.UpdateJobSourceParams{ + ID: jobUuid, + ConnectionSourceID: connUuid, + ConnectionOptions: &pg_models.JobSourceOptions{ + PostgresOptions: &pg_models.PostgresSourceOptions{ + Schemas: []*pg_models.PostgresSourceSchemaOption{ + {Schema: "schema", Tables: []*pg_models.PostgresSourceTableOption{{Table: "table-1", WhereClause: &whereClause}}}, + }, + }, + }, + UpdatedByID: userUuid, + }).Return(db_queries.NeosyncApiJob{}, nil) + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + err := service.SetSqlSourceSubsets(context.Background(), jobUuid, schemas, userUuid) + + assert.NoError(t, err) +} diff --git a/backend/internal/nucleusdb/users.go b/backend/internal/nucleusdb/users.go index 0b5fb4ff95..feefa226f7 100644 --- a/backend/internal/nucleusdb/users.go +++ b/backend/internal/nucleusdb/users.go @@ -51,8 +51,9 @@ func (d *NucleusDb) SetUserByAuth0Id( } userResp = &user } - userResp = &user + return nil } + userResp = &user return nil }); err != nil { return nil, err @@ -83,6 +84,7 @@ func (d *NucleusDb) SetPersonalAccount( return err } } else { + personalAccount = &account _, err = d.Q.GetAccountUserAssociation(ctx, dbtx, db_queries.GetAccountUserAssociationParams{ AccountId: account.ID, UserId: userId, @@ -99,7 +101,6 @@ func (d *NucleusDb) SetPersonalAccount( } } } - personalAccount = &account return nil }); err != nil { return nil, err diff --git a/backend/internal/nucleusdb/users_test.go b/backend/internal/nucleusdb/users_test.go index a62fa32d02..1e04eec4e9 100644 --- a/backend/internal/nucleusdb/users_test.go +++ b/backend/internal/nucleusdb/users_test.go @@ -16,8 +16,264 @@ const ( mockUserId = "d5e29f1f-b920-458c-8b86-f3a180e06d98" mockAccountId = "5629813e-1a35-4874-922c-9827d85f0378" mockTeamName = "team-name" + mockAuth0Id = "643a8663-6b2e-4d29-a0f0-4a0700ff21ea" ) +// SetUserByAuth0Id +func Test_SetUserByAuth0Id(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + ctx := context.Background() + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetUserByAuth0Id", ctx, mockTx, mockAuth0Id).Return(db_queries.NeosyncApiUser{ID: userUuid}, nil) + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetUserByAuth0Id(context.Background(), mockAuth0Id) + + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, userUuid, resp.ID) +} + +func Test_SetUserByAuth0Id_Association_User(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + ctx := context.Background() + var nilUser db_queries.NeosyncApiUser + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetUserByAuth0Id", ctx, mockTx, mockAuth0Id).Return(nilUser, sql.ErrNoRows) + querierMock.On("GetUserAssociationByAuth0Id", ctx, mockTx, mockAuth0Id).Return(db_queries.NeosyncApiUserIdentityProviderAssociation{UserID: userUuid}, nil) + querierMock.On("GetUser", ctx, mockTx, userUuid).Return(db_queries.NeosyncApiUser{ID: userUuid}, nil) + + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetUserByAuth0Id(context.Background(), mockAuth0Id) + + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, userUuid, resp.ID) +} + +func Test_SetUserByAuth0Id_NoAssociation(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + ctx := context.Background() + var nilUser db_queries.NeosyncApiUser + var nilAssociation db_queries.NeosyncApiUserIdentityProviderAssociation + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetUserByAuth0Id", ctx, mockTx, mockAuth0Id).Return(nilUser, sql.ErrNoRows) + querierMock.On("GetUserAssociationByAuth0Id", ctx, mockTx, mockAuth0Id).Return(nilAssociation, sql.ErrNoRows) + querierMock.On("CreateUser", ctx, mockTx).Return(db_queries.NeosyncApiUser{ID: userUuid}, nil) + querierMock.On("CreateAuth0IdentityProviderAssociation", ctx, mockTx, db_queries.CreateAuth0IdentityProviderAssociationParams{ + UserID: userUuid, + Auth0ProviderID: mockAuth0Id, + }).Return(db_queries.NeosyncApiUserIdentityProviderAssociation{UserID: userUuid, + Auth0ProviderID: mockAuth0Id}, nil) + + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetUserByAuth0Id(context.Background(), mockAuth0Id) + + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, userUuid, resp.ID) +} + +func Test_SetUserByAuth0Id_Association_NoUser(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + ctx := context.Background() + var nilUser db_queries.NeosyncApiUser + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetUserByAuth0Id", ctx, mockTx, mockAuth0Id).Return(nilUser, sql.ErrNoRows) + querierMock.On("GetUserAssociationByAuth0Id", ctx, mockTx, mockAuth0Id).Return(db_queries.NeosyncApiUserIdentityProviderAssociation{UserID: userUuid}, nil) + querierMock.On("GetUser", ctx, mockTx, userUuid).Return(nilUser, sql.ErrNoRows) + querierMock.On("CreateUser", ctx, mockTx).Return(db_queries.NeosyncApiUser{ID: userUuid}, nil) + + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetUserByAuth0Id(context.Background(), mockAuth0Id) + + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, userUuid, resp.ID) +} + +func Test_SetUserByAuth0Id_CreateAuth0IdentityProviderAssociation_Error(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + ctx := context.Background() + var nilUser db_queries.NeosyncApiUser + var nilAssociation db_queries.NeosyncApiUserIdentityProviderAssociation + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetUserByAuth0Id", ctx, mockTx, mockAuth0Id).Return(nilUser, sql.ErrNoRows) + querierMock.On("GetUserAssociationByAuth0Id", ctx, mockTx, mockAuth0Id).Return(nilAssociation, sql.ErrNoRows) + querierMock.On("CreateUser", ctx, mockTx).Return(db_queries.NeosyncApiUser{ID: userUuid}, nil) + querierMock.On("CreateAuth0IdentityProviderAssociation", ctx, mockTx, db_queries.CreateAuth0IdentityProviderAssociationParams{ + UserID: userUuid, + Auth0ProviderID: mockAuth0Id, + }).Return(nilAssociation, errors.New("bad news")) + + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetUserByAuth0Id(context.Background(), mockAuth0Id) + + mockTx.AssertNotCalled(t, "Commit", mock.Anything) + assert.Error(t, err) + assert.Nil(t, resp) +} + +// SetPersonalAccount +func Test_SetPersonalAccount(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + accountUuid, _ := ToUuid(mockAccountId) + ctx := context.Background() + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetPersonalAccountByUserId", ctx, mockTx, userUuid).Return(db_queries.NeosyncApiAccount{ID: accountUuid}, nil) + querierMock.On("GetAccountUserAssociation", ctx, mockTx, db_queries.GetAccountUserAssociationParams{ + AccountId: accountUuid, + UserId: userUuid, + }).Return(db_queries.NeosyncApiAccountUserAssociation{}, nil) + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetPersonalAccount(ctx, userUuid) + + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, accountUuid, resp.ID) +} + +func Test_SetPersonalAccount_CreateUserAssociation(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + accountUuid, _ := ToUuid(mockAccountId) + ctx := context.Background() + var nilAssociation db_queries.NeosyncApiAccountUserAssociation + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetPersonalAccountByUserId", ctx, mockTx, userUuid).Return(db_queries.NeosyncApiAccount{ID: accountUuid}, nil) + querierMock.On("GetAccountUserAssociation", ctx, mockTx, db_queries.GetAccountUserAssociationParams{ + AccountId: accountUuid, + UserId: userUuid, + }).Return(nilAssociation, sql.ErrNoRows) + querierMock.On("CreateAccountUserAssociation", ctx, mockTx, db_queries.CreateAccountUserAssociationParams{ + AccountID: accountUuid, + UserID: userUuid, + }).Return(db_queries.NeosyncApiAccountUserAssociation{}, nil) + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetPersonalAccount(ctx, userUuid) + + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, accountUuid, resp.ID) +} + +func Test_SetPersonalAccount_CreateAccount(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + accountUuid, _ := ToUuid(mockAccountId) + ctx := context.Background() + var nilAccount db_queries.NeosyncApiAccount + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetPersonalAccountByUserId", ctx, mockTx, userUuid).Return(nilAccount, sql.ErrNoRows) + querierMock.On("CreatePersonalAccount", ctx, mockTx, "personal").Return(db_queries.NeosyncApiAccount{ID: accountUuid}, nil) + querierMock.On("CreateAccountUserAssociation", ctx, mockTx, db_queries.CreateAccountUserAssociationParams{ + AccountID: accountUuid, + UserID: userUuid, + }).Return(db_queries.NeosyncApiAccountUserAssociation{AccountID: accountUuid, UserID: userUuid}, nil) + mockTx.On("Commit", ctx).Return(nil) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetPersonalAccount(ctx, userUuid) + + assert.NoError(t, err) + assert.NotNil(t, resp) + assert.Equal(t, accountUuid, resp.ID) +} + +func Test_SetPersonalAccount_Rollback(t *testing.T) { + dbtxMock := NewMockDBTX(t) + querierMock := db_queries.NewMockQuerier(t) + mockTx := new(MockTx) + + userUuid, _ := ToUuid(mockUserId) + accountUuid, _ := ToUuid(mockAccountId) + ctx := context.Background() + var nilAccount db_queries.NeosyncApiAccount + + service := New(dbtxMock, querierMock) + + dbtxMock.On("Begin", ctx).Return(mockTx, nil) + querierMock.On("GetPersonalAccountByUserId", ctx, mockTx, userUuid).Return(nilAccount, sql.ErrNoRows) + querierMock.On("CreatePersonalAccount", ctx, mockTx, "personal").Return(db_queries.NeosyncApiAccount{ID: accountUuid}, nil) + querierMock.On("CreateAccountUserAssociation", ctx, mockTx, db_queries.CreateAccountUserAssociationParams{ + AccountID: accountUuid, + UserID: userUuid, + }).Return(db_queries.NeosyncApiAccountUserAssociation{AccountID: accountUuid, UserID: userUuid}, errors.New("boo")) + mockTx.On("Rollback", ctx).Return(nil) + + resp, err := service.SetPersonalAccount(ctx, userUuid) + + mockTx.AssertNotCalled(t, "Commit", ctx) + assert.Error(t, err) + assert.Nil(t, resp) +} + // CreateTeamAccount func Test_CreateTeamAccount(t *testing.T) { dbtxMock := NewMockDBTX(t)