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
This commit is contained in:
parent
8ee7d104a0
commit
6b65b7e7d0
@ -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{})
|
||||
|
||||
|
@ -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,7 +108,38 @@ 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) {
|
||||
return graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: ProjectType,
|
||||
Fields: graphql.Fields{
|
||||
FieldID: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldPublicID: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldName: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldOwnerID: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldDescription: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldCreatedAt: &graphql.Field{
|
||||
Type: graphql.DateTime,
|
||||
},
|
||||
FieldMemberCount: &graphql.Field{
|
||||
Type: graphql.Int,
|
||||
},
|
||||
FieldMembersAndInvitations: &graphql.Field{
|
||||
Type: types.projectMembersAndInvitationsPage,
|
||||
Args: graphql.FieldConfigArgument{
|
||||
CursorArg: &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(types.projectMembersCursor),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
project, _ := p.Source.(*console.Project)
|
||||
|
||||
_, err := console.GetUser(p.Context)
|
||||
@ -121,7 +148,7 @@ func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Objec
|
||||
}
|
||||
|
||||
cursor := cursorArgsToProjectMembersCursor(p.Args[CursorArg].(map[string]interface{}))
|
||||
page, err := service.GetProjectMembers(p.Context, project.ID, cursor, pagingType)
|
||||
page, err := service.GetProjectMembersAndInvitations(p.Context, project.ID, cursor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -152,53 +179,6 @@ func graphqlProject(service *console.Service, types *TypeCreator) *graphql.Objec
|
||||
PageCount: page.PageCount,
|
||||
}
|
||||
return projectMembersPage, nil
|
||||
}
|
||||
|
||||
return graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: ProjectType,
|
||||
Fields: graphql.Fields{
|
||||
FieldID: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldPublicID: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldName: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldOwnerID: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldDescription: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
FieldCreatedAt: &graphql.Field{
|
||||
Type: graphql.DateTime,
|
||||
},
|
||||
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{
|
||||
CursorArg: &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(types.projectMembersCursor),
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
return resolveMembersAndInvites(p, console.MembersAndInvitations)
|
||||
},
|
||||
},
|
||||
FieldAPIKeys: &graphql.Field{
|
||||
|
@ -78,41 +78,16 @@ 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{
|
||||
return graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: ProjectMembersAndInvitationsPageType,
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
func commonProjectMembersPageFields() graphql.Fields {
|
||||
return graphql.Fields{
|
||||
SearchArg: &graphql.Field{
|
||||
Type: graphql.String,
|
||||
},
|
||||
@ -137,7 +112,8 @@ func commonProjectMembersPageFields() graphql.Fields {
|
||||
FieldTotalCount: &graphql.Field{
|
||||
Type: graphql.Int,
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// projectMember encapsulates User and joinedAt.
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user