From 6b65b7e7d04ae9137fa9722771831a41c318cf17 Mon Sep 17 00:00:00 2001 From: Jeremy Wharton Date: Thu, 8 Jun 2023 03:49:53 -0500 Subject: [PATCH] satellite/{console,satellitedb}: clean up obsolete project member code This change removes the obsolete project member paging code. Previously, we implemented functionality for including project invitations in pages of project members. However, the satellite frontend still expected API responses to use the old paging style, so the related code could not be removed right away. Now that the frontend has been updated, this code is no longer necessary. References #5855 Change-Id: I12fdaaeb869977c4d87a0d50b9a7b11c68552c82 --- .../consoleweb/consoleql/mutation_test.go | 12 +- .../console/consoleweb/consoleql/project.go | 98 ++++++-------- .../consoleweb/consoleql/projectmember.go | 90 +++++------- .../consoleweb/consoleql/query_test.go | 4 +- .../consoleweb/consoleql/typecreator.go | 6 - .../console/consoleweb/endpoints_test.go | 6 +- satellite/console/projectmembers.go | 15 -- satellite/console/projectmembers_test.go | 14 +- satellite/console/service.go | 10 +- satellite/console/service_test.go | 8 +- satellite/satellitedb/apikeys.go | 20 +-- satellite/satellitedb/projectmembers.go | 128 ------------------ 12 files changed, 108 insertions(+), 303 deletions(-) diff --git a/satellite/console/consoleweb/consoleql/mutation_test.go b/satellite/console/consoleweb/consoleql/mutation_test.go index 1ef00c393..64c1a74c4 100644 --- a/satellite/console/consoleweb/consoleql/mutation_test.go +++ b/satellite/console/consoleweb/consoleql/mutation_test.go @@ -319,7 +319,7 @@ func TestGraphqlMutation(t *testing.T) { data := result.(map[string]interface{}) proj := data[consoleql.AddProjectMembersMutation].(map[string]interface{}) - members := proj[consoleql.FieldMembers].(map[string]interface{}) + members := proj[consoleql.FieldMembersAndInvitations].(map[string]interface{}) projectMembers := members[consoleql.FieldProjectMembers].([]interface{}) assert.Equal(t, project.ID.String(), proj[consoleql.FieldID]) @@ -330,7 +330,7 @@ func TestGraphqlMutation(t *testing.T) { t.Run("Add project members mutation", func(t *testing.T) { query := fmt.Sprintf( - "mutation {addProjectMembers(projectID:\"%s\",email:[\"%s\",\"%s\"]){id,publicId,name,members(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", + "mutation {addProjectMembers(projectID:\"%s\",email:[\"%s\",\"%s\"]){id,publicId,name,membersAndInvitations(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", project.ID.String(), user1.Email, user2.Email, @@ -341,7 +341,7 @@ func TestGraphqlMutation(t *testing.T) { t.Run("Add project members mutation with publicId", func(t *testing.T) { query := fmt.Sprintf( - "mutation {addProjectMembers(publicId:\"%s\",email:[\"%s\"]){id,publicId,name,members(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", + "mutation {addProjectMembers(publicId:\"%s\",email:[\"%s\"]){id,publicId,name,membersAndInvitations(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", project.PublicID.String(), user3.Email, ) @@ -351,7 +351,7 @@ func TestGraphqlMutation(t *testing.T) { t.Run("Fail add project members mutation without ID", func(t *testing.T) { query := fmt.Sprintf( - "mutation {addProjectMembers(email:[\"%s\",\"%s\"]){id,publicId,name,members(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", + "mutation {addProjectMembers(email:[\"%s\",\"%s\"]){id,publicId,name,membersAndInvitations(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{joinedAt}}}}", user1.Email, user2.Email, ) @@ -362,7 +362,7 @@ func TestGraphqlMutation(t *testing.T) { t.Run("Delete project members mutation", func(t *testing.T) { query := fmt.Sprintf( - "mutation {deleteProjectMembers(projectID:\"%s\",email:[\"%s\",\"%s\",\"%s\"]){id,publicId,name,members(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{user{id}}}}}", + "mutation {deleteProjectMembers(projectID:\"%s\",email:[\"%s\",\"%s\",\"%s\"]){id,publicId,name,membersAndInvitations(cursor: { limit: 50, search: \"\", page: 1, order: 1, orderDirection: 2 }){projectMembers{user{id}}}}}", project.ID.String(), user1.Email, user2.Email, @@ -375,7 +375,7 @@ func TestGraphqlMutation(t *testing.T) { data := result.(map[string]interface{}) proj := data[consoleql.DeleteProjectMembersMutation].(map[string]interface{}) - members := proj[consoleql.FieldMembers].(map[string]interface{}) + members := proj[consoleql.FieldMembersAndInvitations].(map[string]interface{}) projectMembers := members[consoleql.FieldProjectMembers].([]interface{}) rootMember := projectMembers[0].(map[string]interface{})[consoleql.UserType].(map[string]interface{}) diff --git a/satellite/console/consoleweb/consoleql/project.go b/satellite/console/consoleweb/consoleql/project.go index cc3b875aa..96e24de4b 100644 --- a/satellite/console/consoleweb/consoleql/project.go +++ b/satellite/console/consoleweb/consoleql/project.go @@ -34,8 +34,6 @@ const ( BucketUsageType = "bucketUsage" // BucketUsagePageType is a graphql type name for bucket usage page. BucketUsagePageType = "bucketUsagePage" - // ProjectMembersPageType is a graphql type name for project members page. - ProjectMembersPageType = "projectMembersPage" // ProjectMembersAndInvitationsPageType is a graphql type name for a page of project members and invitations. ProjectMembersAndInvitationsPageType = "projectMembersAndInvitationsPage" // ProjectMembersCursorInputType is a graphql type name for project members. @@ -54,8 +52,6 @@ const ( FieldBucketName = "bucketName" // FieldDescription is a field name for description. FieldDescription = "description" - // FieldMembers is field name for members. - FieldMembers = "members" // FieldMembersAndInvitations is field name for members and invitations. FieldMembersAndInvitations = "membersAndInvitations" // FieldAPIKeys is a field name for api keys. @@ -112,48 +108,6 @@ const ( // graphqlProject creates *graphql.Object type representation of satellite.ProjectInfo. func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Object { - resolveMembersAndInvites := func(p graphql.ResolveParams, pagingType console.ProjectMembersPagingType) (interface{}, error) { - project, _ := p.Source.(*console.Project) - - _, err := console.GetUser(p.Context) - if err != nil { - return nil, err - } - - cursor := cursorArgsToProjectMembersCursor(p.Args[CursorArg].(map[string]interface{})) - page, err := service.GetProjectMembers(p.Context, project.ID, cursor, pagingType) - if err != nil { - return nil, err - } - - var users []projectMember - for _, member := range page.ProjectMembers { - user, err := service.GetUser(p.Context, member.MemberID) - if err != nil { - return nil, err - } - - users = append(users, projectMember{ - User: user, - JoinedAt: member.CreatedAt, - }) - } - - projectMembersPage := projectMembersPage{ - ProjectMembers: users, - ProjectInvitations: page.ProjectInvitations, - TotalCount: page.TotalCount, - Offset: page.Offset, - Limit: page.Limit, - Order: int(page.Order), - OrderDirection: int(page.OrderDirection), - Search: page.Search, - CurrentPage: page.CurrentPage, - PageCount: page.PageCount, - } - return projectMembersPage, nil - } - return graphql.NewObject(graphql.ObjectConfig{ Name: ProjectType, Fields: graphql.Fields{ @@ -178,18 +132,6 @@ func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Objec FieldMemberCount: &graphql.Field{ Type: graphql.Int, }, - // TODO: Remove once the frontend has been updated to select membersAndInvitations. - FieldMembers: &graphql.Field{ - Type: types.projectMemberPage, - Args: graphql.FieldConfigArgument{ - CursorArg: &graphql.ArgumentConfig{ - Type: graphql.NewNonNull(types.projectMembersCursor), - }, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - return resolveMembersAndInvites(p, console.Members) - }, - }, FieldMembersAndInvitations: &graphql.Field{ Type: types.projectMembersAndInvitationsPage, Args: graphql.FieldConfigArgument{ @@ -198,7 +140,45 @@ func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Objec }, }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { - return resolveMembersAndInvites(p, console.MembersAndInvitations) + project, _ := p.Source.(*console.Project) + + _, err := console.GetUser(p.Context) + if err != nil { + return nil, err + } + + cursor := cursorArgsToProjectMembersCursor(p.Args[CursorArg].(map[string]interface{})) + page, err := service.GetProjectMembersAndInvitations(p.Context, project.ID, cursor) + if err != nil { + return nil, err + } + + var users []projectMember + for _, member := range page.ProjectMembers { + user, err := service.GetUser(p.Context, member.MemberID) + if err != nil { + return nil, err + } + + users = append(users, projectMember{ + User: user, + JoinedAt: member.CreatedAt, + }) + } + + projectMembersPage := projectMembersPage{ + ProjectMembers: users, + ProjectInvitations: page.ProjectInvitations, + TotalCount: page.TotalCount, + Offset: page.Offset, + Limit: page.Limit, + Order: int(page.Order), + OrderDirection: int(page.OrderDirection), + Search: page.Search, + CurrentPage: page.CurrentPage, + PageCount: page.PageCount, + } + return projectMembersPage, nil }, }, FieldAPIKeys: &graphql.Field{ diff --git a/satellite/console/consoleweb/consoleql/projectmember.go b/satellite/console/consoleweb/consoleql/projectmember.go index f05544cde..d0e8a5fe0 100644 --- a/satellite/console/consoleweb/consoleql/projectmember.go +++ b/satellite/console/consoleweb/consoleql/projectmember.go @@ -78,68 +78,44 @@ func graphqlProjectMembersCursor() *graphql.InputObject { }) } -func graphqlProjectMembersPage(types *TypeCreator) *graphql.Object { - fields := graphql.Fields{ - FieldProjectMembers: &graphql.Field{ - Type: graphql.NewList(types.projectMember), - }, - } - for k, v := range commonProjectMembersPageFields() { - fields[k] = v - } - return graphql.NewObject(graphql.ObjectConfig{ - Name: ProjectMembersPageType, - Fields: fields, - }) -} - func graphqlProjectMembersAndInvitationsPage(types *TypeCreator) *graphql.Object { - fields := graphql.Fields{ - FieldProjectMembers: &graphql.Field{ - Type: graphql.NewList(types.projectMember), - }, - FieldProjectInvitations: &graphql.Field{ - Type: graphql.NewList(types.projectInvitation), - }, - } - for k, v := range commonProjectMembersPageFields() { - fields[k] = v - } return graphql.NewObject(graphql.ObjectConfig{ - Name: ProjectMembersAndInvitationsPageType, - Fields: fields, + Name: ProjectMembersAndInvitationsPageType, + Fields: graphql.Fields{ + FieldProjectMembers: &graphql.Field{ + Type: graphql.NewList(types.projectMember), + }, + FieldProjectInvitations: &graphql.Field{ + Type: graphql.NewList(types.projectInvitation), + }, + SearchArg: &graphql.Field{ + Type: graphql.String, + }, + LimitArg: &graphql.Field{ + Type: graphql.Int, + }, + OrderArg: &graphql.Field{ + Type: graphql.Int, + }, + OrderDirectionArg: &graphql.Field{ + Type: graphql.Int, + }, + OffsetArg: &graphql.Field{ + Type: graphql.Int, + }, + FieldPageCount: &graphql.Field{ + Type: graphql.Int, + }, + FieldCurrentPage: &graphql.Field{ + Type: graphql.Int, + }, + FieldTotalCount: &graphql.Field{ + Type: graphql.Int, + }, + }, }) } -func commonProjectMembersPageFields() graphql.Fields { - return graphql.Fields{ - SearchArg: &graphql.Field{ - Type: graphql.String, - }, - LimitArg: &graphql.Field{ - Type: graphql.Int, - }, - OrderArg: &graphql.Field{ - Type: graphql.Int, - }, - OrderDirectionArg: &graphql.Field{ - Type: graphql.Int, - }, - OffsetArg: &graphql.Field{ - Type: graphql.Int, - }, - FieldPageCount: &graphql.Field{ - Type: graphql.Int, - }, - FieldCurrentPage: &graphql.Field{ - Type: graphql.Int, - }, - FieldTotalCount: &graphql.Field{ - Type: graphql.Int, - }, - } -} - // projectMember encapsulates User and joinedAt. type projectMember struct { User *console.User diff --git a/satellite/console/consoleweb/consoleql/query_test.go b/satellite/console/consoleweb/consoleql/query_test.go index ab0362077..ad551da86 100644 --- a/satellite/console/consoleweb/consoleql/query_test.go +++ b/satellite/console/consoleweb/consoleql/query_test.go @@ -286,7 +286,7 @@ func TestGraphqlQuery(t *testing.T) { t.Run("Project query team members", func(t *testing.T) { query := fmt.Sprintf( - "query {project(id: \"%s\") {members( cursor: { limit: %d, search: \"%s\", page: %d, order: %d, orderDirection: %d } ) { projectMembers{ user { id, fullName, shortName, email, createdAt }, joinedAt }, search, limit, order, offset, pageCount, currentPage, totalCount } } }", + "query {project(id: \"%s\") {membersAndInvitations( cursor: { limit: %d, search: \"%s\", page: %d, order: %d, orderDirection: %d } ) { projectMembers{ user { id, fullName, shortName, email, createdAt }, joinedAt }, search, limit, order, offset, pageCount, currentPage, totalCount } } }", createdProject.ID.String(), 5, "", @@ -298,7 +298,7 @@ func TestGraphqlQuery(t *testing.T) { data := result.(map[string]interface{}) project := data[consoleql.ProjectQuery].(map[string]interface{}) - members := project[consoleql.FieldMembers].(map[string]interface{}) + members := project[consoleql.FieldMembersAndInvitations].(map[string]interface{}) projectMembers := members[consoleql.FieldProjectMembers].([]interface{}) assert.Equal(t, 3, len(projectMembers)) diff --git a/satellite/console/consoleweb/consoleql/typecreator.go b/satellite/console/consoleweb/consoleql/typecreator.go index 060d1edcf..9393a21fe 100644 --- a/satellite/console/consoleweb/consoleql/typecreator.go +++ b/satellite/console/consoleweb/consoleql/typecreator.go @@ -25,7 +25,6 @@ type TypeCreator struct { bucketUsagePage *graphql.Object projectMember *graphql.Object projectInvitation *graphql.Object - projectMemberPage *graphql.Object projectMembersAndInvitationsPage *graphql.Object apiKeyPage *graphql.Object apiKeyInfo *graphql.Object @@ -119,11 +118,6 @@ func (c *TypeCreator) Create(log *zap.Logger, service *console.Service, mailServ return err } - c.projectMemberPage = graphqlProjectMembersPage(c) - if err := c.projectMemberPage.Error(); err != nil { - return err - } - c.projectMembersAndInvitationsPage = graphqlProjectMembersAndInvitationsPage(c) if err := c.projectMembersAndInvitationsPage.Error(); err != nil { return err diff --git a/satellite/console/consoleweb/endpoints_test.go b/satellite/console/consoleweb/endpoints_test.go index ababd5568..00daf76d6 100644 --- a/satellite/console/consoleweb/endpoints_test.go +++ b/satellite/console/consoleweb/endpoints_test.go @@ -575,7 +575,7 @@ func TestProjects(t *testing.T) { "query": ` query ($projectId: String!, $limit: Int!, $search: String!, $page: Int!, $order: Int!, $orderDirection: Int!) { project(id: $projectId) { - members(cursor: {limit: $limit, search: $search, page: $page, order: $order, orderDirection: $orderDirection}) { + membersAndInvitations(cursor: {limit: $limit, search: $search, page: $page, order: $order, orderDirection: $orderDirection}) { projectMembers { user { id @@ -598,7 +598,7 @@ func TestProjects(t *testing.T) { __typename } }`})) - require.Contains(t, body, "projectMembersPage") + require.Contains(t, body, "projectMembersAndInvitationsPage") require.Equal(t, http.StatusOK, resp.StatusCode) } @@ -787,7 +787,7 @@ func TestWrongUser(t *testing.T) { "query": ` query ($projectId: String!, $limit: Int!, $search: String!, $page: Int!, $order: Int!, $orderDirection: Int!) { project(id: $projectId) { - members(cursor: {limit: $limit, search: $search, page: $page, order: $order, orderDirection: $orderDirection}) { + membersAndInvitations(cursor: {limit: $limit, search: $search, page: $page, order: $order, orderDirection: $orderDirection}) { projectMembers { user { id diff --git a/satellite/console/projectmembers.go b/satellite/console/projectmembers.go index af9b408fb..97c1bcc27 100644 --- a/satellite/console/projectmembers.go +++ b/satellite/console/projectmembers.go @@ -16,9 +16,6 @@ import ( type ProjectMembers interface { // GetByMemberID is a method for querying project members from the database by memberID. GetByMemberID(ctx context.Context, memberID uuid.UUID) ([]ProjectMember, error) - // GetPagedByProjectID is a method for querying project members from the database by projectID and cursor. - // TODO: Remove once all uses have been replaced by GetPagedWithInvitationsByProjectID. - GetPagedByProjectID(ctx context.Context, projectID uuid.UUID, cursor ProjectMembersCursor) (*ProjectMembersPage, error) // GetPagedWithInvitationsByProjectID is a method for querying project members and invitations from the database by projectID and cursor. GetPagedWithInvitationsByProjectID(ctx context.Context, projectID uuid.UUID, cursor ProjectMembersCursor) (*ProjectMembersPage, error) // Insert is a method for inserting project member into the database. @@ -62,18 +59,6 @@ type ProjectMembersPage struct { TotalCount uint64 } -// ProjectMembersPagingType determines what types of results should be returned -// in a project members page. -type ProjectMembersPagingType int - -const ( - // Members indicates that only project members should be returned in a project members page. - Members ProjectMembersPagingType = iota - // MembersAndInvitations indicates that project members and project invitations should be - // returned in a project members page. - MembersAndInvitations -) - // ProjectMemberOrder is used for querying project members in specified order. type ProjectMemberOrder int8 diff --git a/satellite/console/projectmembers_test.go b/satellite/console/projectmembers_test.go index 36bc953a7..a5eb07264 100644 --- a/satellite/console/projectmembers_test.go +++ b/satellite/console/projectmembers_test.go @@ -80,7 +80,7 @@ func TestProjectMembersRepository(t *testing.T) { t.Run("Get paged", func(t *testing.T) { // sql injection test. F.E '%SomeText%' = > ''%SomeText%' OR 'x' != '%'' will be true - members, err := projectMembers.GetPagedByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 6, Search: "son%' OR 'x' != '", Order: 2, Page: 1}) + members, err := projectMembers.GetPagedWithInvitationsByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 6, Search: "son%' OR 'x' != '", Order: 2, Page: 1}) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, uint64(0), members.TotalCount) @@ -88,7 +88,7 @@ func TestProjectMembersRepository(t *testing.T) { assert.Equal(t, uint(0), members.PageCount) assert.Equal(t, 0, len(members.ProjectMembers)) - members, err = projectMembers.GetPagedByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 3, Search: "", Order: 1, Page: 1}) + members, err = projectMembers.GetPagedWithInvitationsByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 3, Search: "", Order: 1, Page: 1}) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, uint64(5), members.TotalCount) @@ -96,25 +96,25 @@ func TestProjectMembersRepository(t *testing.T) { assert.Equal(t, uint(2), members.PageCount) assert.Equal(t, 3, len(members.ProjectMembers)) - members, err = projectMembers.GetPagedByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 2, Search: "iam", Order: 2, Page: 1}) // TODO: fix case sensitity issues and change back to "Liam" + members, err = projectMembers.GetPagedWithInvitationsByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 2, Search: "iam", Order: 2, Page: 1}) // TODO: fix case sensitity issues and change back to "Liam" assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, uint64(2), members.TotalCount) assert.Equal(t, 2, len(members.ProjectMembers)) - members, err = projectMembers.GetPagedByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 2, Search: "iam", Order: 1, Page: 1}) // TODO: fix case sensitity issues and change back to "Liam" + members, err = projectMembers.GetPagedWithInvitationsByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 2, Search: "iam", Order: 1, Page: 1}) // TODO: fix case sensitity issues and change back to "Liam" assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, uint64(2), members.TotalCount) assert.Equal(t, 2, len(members.ProjectMembers)) - members, err = projectMembers.GetPagedByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 6, Search: "son", Order: 123, Page: 1}) + members, err = projectMembers.GetPagedWithInvitationsByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 6, Search: "son", Order: 123, Page: 1}) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, uint64(5), members.TotalCount) assert.Equal(t, 5, len(members.ProjectMembers)) - members, err = projectMembers.GetPagedByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 6, Search: "son", Order: 2, Page: 1}) + members, err = projectMembers.GetPagedWithInvitationsByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{Limit: 6, Search: "son", Order: 2, Page: 1}) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, uint64(5), members.TotalCount) @@ -141,7 +141,7 @@ func TestProjectMembersRepository(t *testing.T) { err := projectMembers.Delete(ctx, createdUsers[0].ID, createdProjects[0].ID) assert.NoError(t, err) - projMembers, err := projectMembers.GetPagedByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{ + projMembers, err := projectMembers.GetPagedWithInvitationsByProjectID(ctx, createdProjects[0].ID, console.ProjectMembersCursor{ Order: 1, Search: "", Limit: 100, diff --git a/satellite/console/service.go b/satellite/console/service.go index 196228e9b..4d61c4b0c 100644 --- a/satellite/console/service.go +++ b/satellite/console/service.go @@ -2118,8 +2118,8 @@ func (s *Service) DeleteProjectMembersAndInvitations(ctx context.Context, projec return Error.Wrap(err) } -// GetProjectMembers returns ProjectMembers for given Project. -func (s *Service) GetProjectMembers(ctx context.Context, projectID uuid.UUID, cursor ProjectMembersCursor, pagingType ProjectMembersPagingType) (pmp *ProjectMembersPage, err error) { +// GetProjectMembersAndInvitations returns the project members and invitations for a given project. +func (s *Service) GetProjectMembersAndInvitations(ctx context.Context, projectID uuid.UUID, cursor ProjectMembersCursor) (pmp *ProjectMembersPage, err error) { defer mon.Task()(&ctx)(&err) user, err := s.getUserAndAuditLog(ctx, "get project members", zap.String("projectID", projectID.String())) @@ -2136,11 +2136,7 @@ func (s *Service) GetProjectMembers(ctx context.Context, projectID uuid.UUID, cu cursor.Limit = maxLimit } - if pagingType == MembersAndInvitations { - pmp, err = s.store.ProjectMembers().GetPagedWithInvitationsByProjectID(ctx, projectID, cursor) - } else { - pmp, err = s.store.ProjectMembers().GetPagedByProjectID(ctx, projectID, cursor) - } + pmp, err = s.store.ProjectMembers().GetPagedWithInvitationsByProjectID(ctx, projectID, cursor) if err != nil { return nil, Error.Wrap(err) } diff --git a/satellite/console/service_test.go b/satellite/console/service_test.go index 4d5c2daee..777fe0904 100644 --- a/satellite/console/service_test.go +++ b/satellite/console/service_test.go @@ -287,19 +287,19 @@ func TestService(t *testing.T) { require.Nil(t, addedUsers) }) - t.Run("GetProjectMembers", func(t *testing.T) { + t.Run("GetProjectMembersAndInvitations", func(t *testing.T) { // Getting the project members of an own project that one is a part of should work - userPage, err := service.GetProjectMembers(userCtx1, up1Proj.ID, console.ProjectMembersCursor{Page: 1, Limit: 10}, console.Members) + userPage, err := service.GetProjectMembersAndInvitations(userCtx1, up1Proj.ID, console.ProjectMembersCursor{Page: 1, Limit: 10}) require.NoError(t, err) require.Len(t, userPage.ProjectMembers, 2) // Getting the project members of a foreign project that one is a part of should work - userPage, err = service.GetProjectMembers(userCtx2, up1Proj.ID, console.ProjectMembersCursor{Page: 1, Limit: 10}, console.Members) + userPage, err = service.GetProjectMembersAndInvitations(userCtx2, up1Proj.ID, console.ProjectMembersCursor{Page: 1, Limit: 10}) require.NoError(t, err) require.Len(t, userPage.ProjectMembers, 2) // Getting the project members of a foreign project that one is not a part of should not work - userPage, err = service.GetProjectMembers(userCtx1, up2Proj.ID, console.ProjectMembersCursor{Page: 1, Limit: 10}, console.Members) + userPage, err = service.GetProjectMembersAndInvitations(userCtx1, up2Proj.ID, console.ProjectMembersCursor{Page: 1, Limit: 10}) require.Error(t, err) require.Nil(t, userPage) }) diff --git a/satellite/satellitedb/apikeys.go b/satellite/satellitedb/apikeys.go index 94ea17652..2b923d641 100644 --- a/satellite/satellitedb/apikeys.go +++ b/satellite/satellitedb/apikeys.go @@ -79,8 +79,7 @@ func (keys *apikeys) GetPagedByProjectID(ctx context.Context, projectID uuid.UUI WHERE ak.project_id = ? AND ak.project_id = p.id AND lower(ak.name) LIKE ? - ORDER BY ` + sanitizedAPIKeyOrderColumnName(cursor.Order) + ` - ` + sanitizeOrderDirectionName(page.OrderDirection) + ` + ` + apikeySortClause(cursor.Order, page.OrderDirection) + ` LIMIT ? OFFSET ?`) rows, err := keys.db.QueryContext(ctx, @@ -171,8 +170,7 @@ func (keys *apikeys) GetAllNamesByProjectID(ctx context.Context, projectID uuid. SELECT ak.name FROM api_keys ak WHERE ak.project_id = ? - ORDER BY ` + sanitizedAPIKeyOrderColumnName(console.KeyName) + ` - ` + sanitizeOrderDirectionName(console.Ascending), + ` + apikeySortClause(console.KeyName, console.Ascending), ) rows, err := keys.db.QueryContext(ctx, query, projectID[:]) @@ -285,11 +283,15 @@ func fromDBXAPIKey(ctx context.Context, row *dbx.ApiKey_Project_PublicId_Row) (_ return result, nil } -// sanitizedAPIKeyOrderColumnName return valid order by column. -func sanitizedAPIKeyOrderColumnName(pmo console.APIKeyOrder) string { - if pmo == 2 { - return "ak.created_at" +// apikeySortClause returns what ORDER BY clause should be used when sorting API key results. +func apikeySortClause(order console.APIKeyOrder, direction console.OrderDirection) string { + dirStr := "ASC" + if direction == console.Descending { + dirStr = "DESC" } - return "lower(ak.name)" + if order == console.CreationDate { + return "ORDER BY ak.created_at " + dirStr + ", ak.name, ak.project_id" + } + return "ORDER BY LOWER(ak.name) " + dirStr + ", ak.name, ak.project_id" } diff --git a/satellite/satellitedb/projectmembers.go b/satellite/satellitedb/projectmembers.go index 8d8ede680..3ac4bdb2f 100644 --- a/satellite/satellitedb/projectmembers.go +++ b/satellite/satellitedb/projectmembers.go @@ -35,114 +35,6 @@ func (pm *projectMembers) GetByMemberID(ctx context.Context, memberID uuid.UUID) return projectMembersFromDbxSlice(ctx, projectMembersDbx) } -// GetByProjectID is a method for querying project members from the database by projectID, offset and limit. -// TODO: Remove once all uses have been replaced by GetPagedWithInvitationsByProjectID. -func (pm *projectMembers) GetPagedByProjectID(ctx context.Context, projectID uuid.UUID, cursor console.ProjectMembersCursor) (_ *console.ProjectMembersPage, err error) { - defer mon.Task()(&ctx)(&err) - - search := "%" + strings.ReplaceAll(cursor.Search, " ", "%") + "%" - - if cursor.Limit > 50 { - cursor.Limit = 50 - } - - if cursor.Page == 0 { - return nil, errs.New("page cannot be 0") - } - - page := &console.ProjectMembersPage{ - Search: cursor.Search, - Limit: cursor.Limit, - Offset: uint64((cursor.Page - 1) * cursor.Limit), - Order: cursor.Order, - OrderDirection: cursor.OrderDirection, - } - - countQuery := pm.db.Rebind(` - SELECT COUNT(*) - FROM project_members pm - INNER JOIN users u ON pm.member_id = u.id - WHERE pm.project_id = ? - AND ( u.email LIKE ? OR - u.full_name LIKE ? OR - u.short_name LIKE ? - )`) - - countRow := pm.db.QueryRowContext(ctx, - countQuery, - projectID[:], - search, - search, - search) - - err = countRow.Scan(&page.TotalCount) - if err != nil { - return nil, err - } - if page.TotalCount == 0 { - return page, nil - } - if page.Offset > page.TotalCount-1 { - return nil, errs.New("page is out of range") - } - // TODO: LIKE is case-sensitive postgres, however this should be case-insensitive and possibly allow typos - reboundQuery := pm.db.Rebind(` - SELECT pm.* - FROM project_members pm - INNER JOIN users u ON pm.member_id = u.id - WHERE pm.project_id = ? - AND ( u.email LIKE ? OR - u.full_name LIKE ? OR - u.short_name LIKE ? ) - ORDER BY ` + sanitizedOrderColumnName(cursor.Order) + ` - ` + sanitizeOrderDirectionName(page.OrderDirection) + ` - LIMIT ? OFFSET ?`) - - rows, err := pm.db.QueryContext(ctx, - reboundQuery, - projectID[:], - search, - search, - search, - page.Limit, - page.Offset) - - defer func() { - err = errs.Combine(err, rows.Close()) - }() - - if err != nil { - return nil, err - } - - var projectMembers []console.ProjectMember - for rows.Next() { - pm := console.ProjectMember{} - - err = rows.Scan(&pm.MemberID, &pm.ProjectID, &pm.CreatedAt) - if err != nil { - return nil, err - } - - projectMembers = append(projectMembers, pm) - } - if err := rows.Err(); err != nil { - return nil, err - } - - page.ProjectMembers = projectMembers - page.Order = cursor.Order - - page.PageCount = uint(page.TotalCount / uint64(cursor.Limit)) - if page.TotalCount%uint64(cursor.Limit) != 0 { - page.PageCount++ - } - - page.CurrentPage = cursor.Page - - return page, err -} - // GetPagedWithInvitationsByProjectID is a method for querying project members and invitations from the database by projectID, offset and limit. func (pm *projectMembers) GetPagedWithInvitationsByProjectID(ctx context.Context, projectID uuid.UUID, cursor console.ProjectMembersCursor) (_ *console.ProjectMembersPage, err error) { defer mon.Task()(&ctx)(&err) @@ -341,26 +233,6 @@ func projectMemberFromDBX(ctx context.Context, projectMember *dbx.ProjectMember) }, nil } -// sanitizedOrderColumnName return valid order by column. -func sanitizedOrderColumnName(pmo console.ProjectMemberOrder) string { - switch pmo { - case 2: - return "u.email" - case 3: - return "pm.created_at" - default: - return "u.full_name" - } -} - -func sanitizeOrderDirectionName(pmo console.OrderDirection) string { - if pmo == 2 { - return "DESC" - } - - return "ASC" -} - // projectMembersSortClause returns what ORDER BY clause should be used when sorting project member results. func projectMembersSortClause(order console.ProjectMemberOrder, direction console.OrderDirection) string { dirStr := "ASC"