Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8c0350e

Browse files
authored
feat: add a paginated organization members endpoint (#16835)
Closes [coder/internal#460](coder/internal#460)
1 parent 191b0ef commit 8c0350e

File tree

18 files changed

+548
-1
lines changed

18 files changed

+548
-1
lines changed

coderd/apidoc/docs.go

+64
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+60
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

+1
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,7 @@ func New(options *Options) *API {
10021002
})
10031003
})
10041004
})
1005+
r.Get("/paginated-members", api.paginatedMembers)
10051006
r.Route("/members", func(r chi.Router) {
10061007
r.Get("/", api.listMembers)
10071008
r.Route("/roles", func(r chi.Router) {

coderd/database/dbauthz/dbauthz.go

+8
Original file line numberDiff line numberDiff line change
@@ -3581,6 +3581,14 @@ func (q *querier) OrganizationMembers(ctx context.Context, arg database.Organiza
35813581
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.OrganizationMembers)(ctx, arg)
35823582
}
35833583

3584+
func (q *querier) PaginatedOrganizationMembers(ctx context.Context, arg database.PaginatedOrganizationMembersParams) ([]database.PaginatedOrganizationMembersRow, error) {
3585+
// Required to have permission to read all members in the organization
3586+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOrganizationMember.InOrg(arg.OrganizationID)); err != nil {
3587+
return nil, err
3588+
}
3589+
return q.db.PaginatedOrganizationMembers(ctx, arg)
3590+
}
3591+
35843592
func (q *querier) ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate(ctx context.Context, templateID uuid.UUID) error {
35853593
template, err := q.db.GetTemplateByID(ctx, templateID)
35863594
if err != nil {

coderd/database/dbauthz/dbauthz_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,32 @@ func (s *MethodTestSuite) TestOrganization() {
985985
mem, policy.ActionRead,
986986
)
987987
}))
988+
s.Run("PaginatedOrganizationMembers", s.Subtest(func(db database.Store, check *expects) {
989+
o := dbgen.Organization(s.T(), db, database.Organization{})
990+
u := dbgen.User(s.T(), db, database.User{})
991+
mem := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{
992+
OrganizationID: o.ID,
993+
UserID: u.ID,
994+
Roles: []string{rbac.RoleOrgAdmin()},
995+
})
996+
997+
check.Args(database.PaginatedOrganizationMembersParams{
998+
OrganizationID: o.ID,
999+
LimitOpt: 0,
1000+
}).Asserts(
1001+
rbac.ResourceOrganizationMember.InOrg(o.ID), policy.ActionRead,
1002+
).Returns([]database.PaginatedOrganizationMembersRow{
1003+
{
1004+
OrganizationMember: mem,
1005+
Username: u.Username,
1006+
AvatarURL: u.AvatarURL,
1007+
Name: u.Name,
1008+
Email: u.Email,
1009+
GlobalRoles: u.RBACRoles,
1010+
Count: 1,
1011+
},
1012+
})
1013+
}))
9881014
s.Run("UpdateMemberRoles", s.Subtest(func(db database.Store, check *expects) {
9891015
o := dbgen.Organization(s.T(), db, database.Organization{})
9901016
u := dbgen.User(s.T(), db, database.User{})

coderd/database/dbauthz/setup_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ func asserts(inputs ...any) []AssertRBAC {
503503
// Could be the string type.
504504
actionAsString, ok := inputs[i+1].(string)
505505
if !ok {
506-
panic(fmt.Sprintf("action '%q' not a supported action", actionAsString))
506+
panic(fmt.Sprintf("action '%T' not a supported action", inputs[i+1]))
507507
}
508508
action = policy.Action(actionAsString)
509509
}

coderd/database/dbmem/dbmem.go

+47
Original file line numberDiff line numberDiff line change
@@ -9584,6 +9584,53 @@ func (q *FakeQuerier) OrganizationMembers(_ context.Context, arg database.Organi
95849584
return tmp, nil
95859585
}
95869586

9587+
func (q *FakeQuerier) PaginatedOrganizationMembers(_ context.Context, arg database.PaginatedOrganizationMembersParams) ([]database.PaginatedOrganizationMembersRow, error) {
9588+
err := validateDatabaseType(arg)
9589+
if err != nil {
9590+
return nil, err
9591+
}
9592+
9593+
q.mutex.RLock()
9594+
defer q.mutex.RUnlock()
9595+
9596+
// All of the members in the organization
9597+
orgMembers := make([]database.OrganizationMember, 0)
9598+
for _, mem := range q.organizationMembers {
9599+
if arg.OrganizationID != uuid.Nil && mem.OrganizationID != arg.OrganizationID {
9600+
continue
9601+
}
9602+
9603+
orgMembers = append(orgMembers, mem)
9604+
}
9605+
9606+
selectedMembers := make([]database.PaginatedOrganizationMembersRow, 0)
9607+
9608+
skippedMembers := 0
9609+
for _, organizationMember := range q.organizationMembers {
9610+
if skippedMembers < int(arg.OffsetOpt) {
9611+
skippedMembers++
9612+
continue
9613+
}
9614+
9615+
// if the limit is set to 0 we treat that as returning all of the org members
9616+
if int(arg.LimitOpt) != 0 && len(selectedMembers) >= int(arg.LimitOpt) {
9617+
break
9618+
}
9619+
9620+
user, _ := q.getUserByIDNoLock(organizationMember.UserID)
9621+
selectedMembers = append(selectedMembers, database.PaginatedOrganizationMembersRow{
9622+
OrganizationMember: organizationMember,
9623+
Username: user.Username,
9624+
AvatarURL: user.AvatarURL,
9625+
Name: user.Name,
9626+
Email: user.Email,
9627+
GlobalRoles: user.RBACRoles,
9628+
Count: int64(len(orgMembers)),
9629+
})
9630+
}
9631+
return selectedMembers, nil
9632+
}
9633+
95879634
func (q *FakeQuerier) ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate(_ context.Context, templateID uuid.UUID) error {
95889635
err := validateDatabaseType(templateID)
95899636
if err != nil {

coderd/database/dbmetrics/querymetrics.go

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/modelmethods.go

+4
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ func (m OrganizationMembersRow) RBACObject() rbac.Object {
256256
return m.OrganizationMember.RBACObject()
257257
}
258258

259+
func (m PaginatedOrganizationMembersRow) RBACObject() rbac.Object {
260+
return m.OrganizationMember.RBACObject()
261+
}
262+
259263
func (m GetOrganizationIDsByMemberIDsRow) RBACObject() rbac.Object {
260264
// TODO: This feels incorrect as we are really returning a list of orgmembers.
261265
// This return type should be refactored to return a list of orgmembers, not this

coderd/database/querier.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)