http: GET /api/users (list)
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
// api_users.go — JSON handlers for the user-management surface.
|
||||
//
|
||||
// All endpoints in this file are admin-only; gating happens at the
|
||||
// route-mount site (server.go's admin band).
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
stdhttp "net/http"
|
||||
)
|
||||
|
||||
type listUsersResponse struct {
|
||||
Users []apiUser `json:"users"`
|
||||
}
|
||||
|
||||
type apiUser struct {
|
||||
ID string `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
Email *string `json:"email,omitempty"`
|
||||
Disabled bool `json:"disabled"`
|
||||
MustChangePassword bool `json:"must_change_password"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
LastLoginAt *string `json:"last_login_at,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Server) handleAPIUsersList(w stdhttp.ResponseWriter, r *stdhttp.Request) {
|
||||
users, err := s.deps.Store.ListUsers(r.Context())
|
||||
if err != nil {
|
||||
slog.Error("api users: list", "err", err)
|
||||
writeJSONError(w, stdhttp.StatusInternalServerError, "internal", err.Error())
|
||||
return
|
||||
}
|
||||
out := make([]apiUser, len(users))
|
||||
for i, u := range users {
|
||||
var lastLogin *string
|
||||
if u.LastLoginAt != nil {
|
||||
s := u.LastLoginAt.UTC().Format("2006-01-02T15:04:05Z")
|
||||
lastLogin = &s
|
||||
}
|
||||
out[i] = apiUser{
|
||||
ID: u.ID, Username: u.Username, Role: string(u.Role),
|
||||
Email: u.Email, Disabled: u.DisabledAt != nil,
|
||||
MustChangePassword: u.MustChangePassword,
|
||||
CreatedAt: u.CreatedAt.UTC().Format("2006-01-02T15:04:05Z"),
|
||||
LastLoginAt: lastLogin,
|
||||
}
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
_ = json.NewEncoder(w).Encode(listUsersResponse{Users: out})
|
||||
}
|
||||
Reference in New Issue
Block a user