From 342bef776781a8a833dba64480c446ed685301ee Mon Sep 17 00:00:00 2001 From: Jim Date: Thu, 18 Jun 2020 14:53:11 -0400 Subject: [PATCH] listing projects and organizations (#124) --- internal/iam/repository_scope.go | 23 ++++ internal/iam/repository_scope_test.go | 156 ++++++++++++++++++++++++++ internal/iam/testing.go | 21 +++- internal/iam/testing_test.go | 18 +++ 4 files changed, 216 insertions(+), 2 deletions(-) diff --git a/internal/iam/repository_scope.go b/internal/iam/repository_scope.go index 357d0d9fab..af4198c0f4 100644 --- a/internal/iam/repository_scope.go +++ b/internal/iam/repository_scope.go @@ -120,3 +120,26 @@ func (r *Repository) DeleteScope(ctx context.Context, withPublicId string, opt . } return rowsDeleted, nil } + +// ListProjects in an organization and supports the WithLimit option. +func (r *Repository) ListProjects(ctx context.Context, withOrganizationId string, opt ...Option) ([]*Scope, error) { + if withOrganizationId == "" { + return nil, fmt.Errorf("list projects: missing organization id %w", db.ErrInvalidParameter) + } + var projects []*Scope + err := r.list(ctx, &projects, "parent_id = ? and type = ?", []interface{}{withOrganizationId, ProjectScope.String()}, opt...) + if err != nil { + return nil, fmt.Errorf("list projects: %w", err) + } + return projects, nil +} + +// ListOrganizations and supports the WithLimit option. +func (r *Repository) ListOrganizations(ctx context.Context, opt ...Option) ([]*Scope, error) { + var projects []*Scope + err := r.list(ctx, &projects, "type = ?", []interface{}{OrganizationScope.String()}, opt...) + if err != nil { + return nil, fmt.Errorf("list organizations: %w", err) + } + return projects, nil +} diff --git a/internal/iam/repository_scope_test.go b/internal/iam/repository_scope_test.go index 79702099b6..51d6fced29 100644 --- a/internal/iam/repository_scope_test.go +++ b/internal/iam/repository_scope_test.go @@ -493,3 +493,159 @@ func TestRepository_UpdateScope(t *testing.T) { assert.Nil(updatedScope, "scope should be nil") }) } + +func TestRepository_ListProjects(t *testing.T) { + t.Parallel() + cleanup, conn, _ := db.TestSetup(t, "postgres") + defer func() { + err := cleanup() + assert.NoError(t, err) + err = conn.Close() + assert.NoError(t, err) + }() + const testLimit = 10 + rw := db.New(conn) + wrapper := db.TestWrapper(t) + repo, err := NewRepository(rw, rw, wrapper, WithLimit(testLimit)) + require.NoError(t, err) + org := testOrg(t, conn, "", "") + + type args struct { + withOrganizationId string + opt []Option + } + tests := []struct { + name string + createCnt int + args args + wantCnt int + wantErr bool + }{ + { + name: "no-limit", + createCnt: repo.defaultLimit + 1, + args: args{ + withOrganizationId: org.PublicId, + opt: []Option{WithLimit(-1)}, + }, + wantCnt: repo.defaultLimit + 1, + wantErr: false, + }, + { + name: "default-limit", + createCnt: repo.defaultLimit + 1, + args: args{ + withOrganizationId: org.PublicId, + }, + wantCnt: repo.defaultLimit, + wantErr: false, + }, + { + name: "custom-limit", + createCnt: repo.defaultLimit + 1, + args: args{ + withOrganizationId: org.PublicId, + opt: []Option{WithLimit(3)}, + }, + wantCnt: 3, + wantErr: false, + }, + { + name: "bad-org", + createCnt: 1, + args: args{ + withOrganizationId: "bad-id", + }, + wantCnt: 0, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + require.NoError(conn.Where("public_id != ?", org.PublicId).Delete(allocScope()).Error) + testProjects := []*Scope{} + for i := 0; i < tt.createCnt; i++ { + testProjects = append(testProjects, testProject(t, conn, org.PublicId)) + } + assert.Equal(tt.createCnt, len(testProjects)) + got, err := repo.ListProjects(context.Background(), tt.args.withOrganizationId, tt.args.opt...) + if tt.wantErr { + require.Error(err) + return + } + require.NoError(err) + assert.Equal(tt.wantCnt, len(got)) + }) + } +} + +func TestRepository_ListOrganizations(t *testing.T) { + t.Parallel() + cleanup, conn, _ := db.TestSetup(t, "postgres") + defer func() { + err := cleanup() + assert.NoError(t, err) + err = conn.Close() + assert.NoError(t, err) + }() + const testLimit = 10 + rw := db.New(conn) + wrapper := db.TestWrapper(t) + repo, err := NewRepository(rw, rw, wrapper, WithLimit(testLimit)) + require.NoError(t, err) + type args struct { + opt []Option + } + tests := []struct { + name string + createCnt int + args args + wantCnt int + wantErr bool + }{ + { + name: "no-limit", + createCnt: repo.defaultLimit + 1, + args: args{ + opt: []Option{WithLimit(-1)}, + }, + wantCnt: repo.defaultLimit + 1, + wantErr: false, + }, + { + name: "default-limit", + createCnt: repo.defaultLimit + 1, + args: args{}, + wantCnt: repo.defaultLimit, + wantErr: false, + }, + { + name: "custom-limit", + createCnt: repo.defaultLimit + 1, + args: args{ + opt: []Option{WithLimit(3)}, + }, + wantCnt: 3, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + require.NoError(conn.Where("1=1").Delete(allocScope()).Error) + testOrgs := []*Scope{} + for i := 0; i < tt.createCnt; i++ { + testOrgs = append(testOrgs, testOrg(t, conn, "", "")) + } + assert.Equal(tt.createCnt, len(testOrgs)) + got, err := repo.ListOrganizations(context.Background(), tt.args.opt...) + if tt.wantErr { + require.Error(err) + return + } + require.NoError(err) + assert.Equal(tt.wantCnt, len(got)) + }) + } +} diff --git a/internal/iam/testing.go b/internal/iam/testing.go index 9212991a3a..843aada165 100644 --- a/internal/iam/testing.go +++ b/internal/iam/testing.go @@ -54,6 +54,23 @@ func testOrg(t *testing.T, conn *gorm.DB, name, description string) (org *Scope) return o } +func testProject(t *testing.T, conn *gorm.DB, orgId string, opt ...Option) *Scope { + t.Helper() + require := require.New(t) + rw := db.New(conn) + wrapper := db.TestWrapper(t) + repo, err := NewRepository(rw, rw, wrapper) + require.NoError(err) + + p, err := NewProject(orgId, opt...) + require.NoError(err) + p, err = repo.CreateScope(context.Background(), p) + require.NoError(err) + require.NotNil(p) + require.NotEmpty(p.GetPublicId()) + return p +} + func testId(t *testing.T) string { t.Helper() id, err := uuid.GenerateUUID() @@ -107,12 +124,12 @@ func TestRole(t *testing.T, conn *gorm.DB, scopeId string, opt ...Option) *Role } // TestGroup creates a group suitable for testing. -func TestGroup(t *testing.T, conn *gorm.DB, orgId string, opt ...Option) *Group { +func TestGroup(t *testing.T, conn *gorm.DB, scopeId string, opt ...Option) *Group { t.Helper() require := require.New(t) rw := db.New(conn) - grp, err := NewGroup(orgId, opt...) + grp, err := NewGroup(scopeId, opt...) require.NoError(err) id, err := newGroupId() require.NoError(err) diff --git a/internal/iam/testing_test.go b/internal/iam/testing_test.go index e2cdb83218..b347a47a5b 100644 --- a/internal/iam/testing_test.go +++ b/internal/iam/testing_test.go @@ -27,6 +27,24 @@ func Test_testOrg(t *testing.T) { assert.NotEmpty(org.PublicId) } +func Test_testProj(t *testing.T) { + assert := assert.New(t) + + cleanup, conn, _ := db.TestSetup(t, "postgres") + defer func() { + err := cleanup() + assert.NoError(err) + err = conn.Close() + assert.NoError(err) + }() + id := testId(t) + + org := testOrg(t, conn, id, id) + proj := testProject(t, conn, org.PublicId, WithName(id), WithDescription(id)) + assert.Equal(id, proj.Name) + assert.Equal(id, proj.Description) + assert.NotEmpty(proj.PublicId) +} func Test_testId(t *testing.T) { assert := assert.New(t) id := testId(t)