Files
restic-manager/internal/server/http/api_users.go
T
2026-05-05 10:57:25 +01:00

53 lines
1.6 KiB
Go

// 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})
}