Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit88f3691

Browse files
authored
feat: add count to get users endpoint (#5016)
1 parent49b340e commit88f3691

File tree

25 files changed

+420
-478
lines changed

25 files changed

+420
-478
lines changed

‎cli/list.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,12 @@ func list() *cobra.Command {
102102
_,_=fmt.Fprintln(cmd.ErrOrStderr())
103103
returnnil
104104
}
105-
users,err:=client.Users(cmd.Context(), codersdk.UsersRequest{})
105+
userRes,err:=client.Users(cmd.Context(), codersdk.UsersRequest{})
106106
iferr!=nil {
107107
returnerr
108108
}
109109
usersByID:=map[uuid.UUID]codersdk.User{}
110-
for_,user:=rangeusers {
110+
for_,user:=rangeuserRes.Users {
111111
usersByID[user.ID]=user
112112
}
113113

‎cli/userlist.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,20 @@ func userList() *cobra.Command {
3030
iferr!=nil {
3131
returnerr
3232
}
33-
users,err:=client.Users(cmd.Context(), codersdk.UsersRequest{})
33+
res,err:=client.Users(cmd.Context(), codersdk.UsersRequest{})
3434
iferr!=nil {
3535
returnerr
3636
}
3737

3838
out:=""
3939
switchoutputFormat {
4040
case"table","":
41-
out,err=cliui.DisplayTable(users,"Username",columns)
41+
out,err=cliui.DisplayTable(res.Users,"Username",columns)
4242
iferr!=nil {
4343
returnxerrors.Errorf("render table: %w",err)
4444
}
4545
case"json":
46-
outBytes,err:=json.Marshal(users)
46+
outBytes,err:=json.Marshal(res.Users)
4747
iferr!=nil {
4848
returnxerrors.Errorf("marshal users to JSON: %w",err)
4949
}

‎coderd/coderd.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,6 @@ func New(options *Options) *API {
431431
)
432432
r.Post("/",api.postUser)
433433
r.Get("/",api.users)
434-
r.Get("/count",api.userCount)
435434
r.Post("/logout",api.postLogout)
436435
// These routes query information about site wide roles.
437436
r.Route("/roles",func(r chi.Router) {

‎coderd/coderdtest/authorize.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ func AGPLRoutes(a *AuthTester) (map[string]string, map[string]RouteCheck) {
245245

246246
// Endpoints that use the SQLQuery filter.
247247
"GET:/api/v2/workspaces/": {StatusCode:http.StatusOK,NoAuthorize:true},
248-
"GET:/api/v2/users/count": {StatusCode:http.StatusOK,NoAuthorize:true},
249248
}
250249

251250
// Routes like proxy routes support all HTTP methods. A helper func to expand

‎coderd/database/databasefake/databasefake.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ func (q *fakeQuerier) UpdateUserDeletedByID(_ context.Context, params database.U
538538
returnsql.ErrNoRows
539539
}
540540

541-
func (q*fakeQuerier)GetUsers(_ context.Context,params database.GetUsersParams) ([]database.User,error) {
541+
func (q*fakeQuerier)GetUsers(_ context.Context,params database.GetUsersParams) ([]database.GetUsersRow,error) {
542542
q.mutex.RLock()
543543
deferq.mutex.RUnlock()
544544

@@ -579,7 +579,7 @@ func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
579579

580580
// If no users after the time, then we return an empty list.
581581
if!found {
582-
returnnil,sql.ErrNoRows
582+
return[]database.GetUsersRow{},nil
583583
}
584584
}
585585

@@ -617,9 +617,11 @@ func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
617617
users=usersFilteredByRole
618618
}
619619

620+
beforePageCount:=len(users)
621+
620622
ifparams.OffsetOpt>0 {
621623
ifint(params.OffsetOpt)>len(users)-1 {
622-
returnnil,sql.ErrNoRows
624+
return[]database.GetUsersRow{},nil
623625
}
624626
users=users[params.OffsetOpt:]
625627
}
@@ -631,7 +633,30 @@ func (q *fakeQuerier) GetUsers(_ context.Context, params database.GetUsersParams
631633
users=users[:params.LimitOpt]
632634
}
633635

634-
returnusers,nil
636+
returnconvertUsers(users,int64(beforePageCount)),nil
637+
}
638+
639+
funcconvertUsers(users []database.User,countint64) []database.GetUsersRow {
640+
rows:=make([]database.GetUsersRow,len(users))
641+
fori,u:=rangeusers {
642+
rows[i]= database.GetUsersRow{
643+
ID:u.ID,
644+
Email:u.Email,
645+
Username:u.Username,
646+
HashedPassword:u.HashedPassword,
647+
CreatedAt:u.CreatedAt,
648+
UpdatedAt:u.UpdatedAt,
649+
Status:u.Status,
650+
RBACRoles:u.RBACRoles,
651+
LoginType:u.LoginType,
652+
AvatarURL:u.AvatarURL,
653+
Deleted:u.Deleted,
654+
LastSeenAt:u.LastSeenAt,
655+
Count:count,
656+
}
657+
}
658+
659+
returnrows
635660
}
636661

637662
func (q*fakeQuerier)GetUsersByIDs(_ context.Context,ids []uuid.UUID) ([]database.User,error) {

‎coderd/database/modelmethods.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,25 @@ func (User) RBACObject() rbac.Object {
7171
func (License)RBACObject() rbac.Object {
7272
returnrbac.ResourceLicense
7373
}
74+
75+
funcConvertUserRows(rows []GetUsersRow) []User {
76+
users:=make([]User,len(rows))
77+
fori,r:=rangerows {
78+
users[i]=User{
79+
ID:r.ID,
80+
Email:r.Email,
81+
Username:r.Username,
82+
HashedPassword:r.HashedPassword,
83+
CreatedAt:r.CreatedAt,
84+
UpdatedAt:r.UpdatedAt,
85+
Status:r.Status,
86+
RBACRoles:r.RBACRoles,
87+
LoginType:r.LoginType,
88+
AvatarURL:r.AvatarURL,
89+
Deleted:r.Deleted,
90+
LastSeenAt:r.LastSeenAt,
91+
}
92+
}
93+
94+
returnusers
95+
}

‎coderd/database/querier.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries.sql.go

Lines changed: 21 additions & 4 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries/users.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ WHERE
128128

129129
-- name: GetUsers :many
130130
SELECT
131-
*
131+
*,COUNT(*) OVER()AS count
132132
FROM
133133
users
134134
WHERE

‎coderd/telemetry/telemetry.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,11 @@ func (r *remoteReporter) createSnapshot() (*Snapshot, error) {
350350
returnnil
351351
})
352352
eg.Go(func()error {
353-
users,err:=r.options.Database.GetUsers(ctx, database.GetUsersParams{})
353+
userRows,err:=r.options.Database.GetUsers(ctx, database.GetUsersParams{})
354354
iferr!=nil {
355355
returnxerrors.Errorf("get users: %w",err)
356356
}
357+
users:=database.ConvertUserRows(userRows)
357358
varfirstUser database.User
358359
for_,dbUser:=rangeusers {
359360
ifdbUser.Status!=database.UserStatusActive {

‎coderd/users.go

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -198,27 +198,32 @@ func (api *API) users(rw http.ResponseWriter, r *http.Request) {
198198
return
199199
}
200200

201-
users,err:=api.Database.GetUsers(ctx, database.GetUsersParams{
201+
userRows,err:=api.Database.GetUsers(ctx, database.GetUsersParams{
202202
AfterID:paginationParams.AfterID,
203203
OffsetOpt:int32(paginationParams.Offset),
204204
LimitOpt:int32(paginationParams.Limit),
205205
Search:params.Search,
206206
Status:params.Status,
207207
RbacRole:params.RbacRole,
208208
})
209-
iferrors.Is(err,sql.ErrNoRows) {
210-
httpapi.Write(ctx,rw,http.StatusOK, []codersdk.User{})
211-
return
212-
}
213209
iferr!=nil {
214210
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
215211
Message:"Internal error fetching users.",
216212
Detail:err.Error(),
217213
})
218214
return
219215
}
216+
// GetUsers does not return ErrNoRows because it uses a window function to get the count.
217+
// So we need to check if the userRows is empty and return an empty array if so.
218+
iflen(userRows)==0 {
219+
httpapi.Write(ctx,rw,http.StatusOK, codersdk.GetUsersResponse{
220+
Users: []codersdk.User{},
221+
Count:0,
222+
})
223+
return
224+
}
220225

221-
users,err=AuthorizeFilter(api.HTTPAuth,r,rbac.ActionRead,users)
226+
users,err:=AuthorizeFilter(api.HTTPAuth,r,rbac.ActionRead,database.ConvertUserRows(userRows))
222227
iferr!=nil {
223228
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
224229
Message:"Internal error fetching users.",
@@ -248,42 +253,9 @@ func (api *API) users(rw http.ResponseWriter, r *http.Request) {
248253
}
249254

250255
render.Status(r,http.StatusOK)
251-
render.JSON(rw,r,convertUsers(users,organizationIDsByUserID))
252-
}
253-
254-
func (api*API)userCount(rw http.ResponseWriter,r*http.Request) {
255-
ctx:=r.Context()
256-
query:=r.URL.Query().Get("q")
257-
params,errs:=userSearchQuery(query)
258-
iflen(errs)>0 {
259-
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
260-
Message:"Invalid user search query.",
261-
Validations:errs,
262-
})
263-
return
264-
}
265-
266-
sqlFilter,err:=api.HTTPAuth.AuthorizeSQLFilter(r,rbac.ActionRead,rbac.ResourceUser.Type)
267-
iferr!=nil {
268-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
269-
Message:"Internal error preparing sql filter.",
270-
Detail:err.Error(),
271-
})
272-
return
273-
}
274-
275-
count,err:=api.Database.GetAuthorizedUserCount(ctx, database.GetFilteredUserCountParams{
276-
Search:params.Search,
277-
Status:params.Status,
278-
RbacRole:params.RbacRole,
279-
},sqlFilter)
280-
iferr!=nil {
281-
httpapi.InternalServerError(rw,err)
282-
return
283-
}
284-
285-
httpapi.Write(ctx,rw,http.StatusOK, codersdk.UserCountResponse{
286-
Count:count,
256+
render.JSON(rw,r, codersdk.GetUsersResponse{
257+
Users:convertUsers(users,organizationIDsByUserID),
258+
Count:int(userRows[0].Count),
287259
})
288260
}
289261

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp