99 lines
2.6 KiB
Go
99 lines
2.6 KiB
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
"github.com/iliaivanov/spec-kit-remote/cmd/dev-pod-api/internal/model"
|
|
"github.com/iliaivanov/spec-kit-remote/cmd/dev-pod-api/internal/store"
|
|
)
|
|
|
|
func (s *Server) handleGetUserUsage(w http.ResponseWriter, r *http.Request) {
|
|
targetUser := chi.URLParam(r, "user")
|
|
|
|
if !canAccess(r, targetUser) {
|
|
writeError(w, http.StatusForbidden, "access denied")
|
|
return
|
|
}
|
|
|
|
user, err := s.Users.GetUser(r.Context(), targetUser)
|
|
if err != nil {
|
|
if errors.Is(err, store.ErrNotFound) {
|
|
writeError(w, http.StatusNotFound, "user not found")
|
|
return
|
|
}
|
|
writeError(w, http.StatusInternalServerError, "failed to get user")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
usage, err := s.Usage.GetUsage(r.Context(), targetUser, now.Year(), now.Month(), user.Quota.MonthlyPodHours)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "failed to get usage")
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]*model.UsageSummary{
|
|
"current_month": usage,
|
|
})
|
|
}
|
|
|
|
func (s *Server) handleBillingSummary(w http.ResponseWriter, r *http.Request) {
|
|
if RoleFromContext(r.Context()) != model.RoleAdmin {
|
|
writeError(w, http.StatusForbidden, "admin access required")
|
|
return
|
|
}
|
|
|
|
users, err := s.Users.ListUsers(r.Context())
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "failed to list users")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
summaries := make([]model.UserUsageSummary, 0, len(users))
|
|
for _, u := range users {
|
|
usage, err := s.Usage.GetUsage(r.Context(), u.ID, now.Year(), now.Month(), u.Quota.MonthlyPodHours)
|
|
if err != nil {
|
|
s.Logger.Error("failed to get usage for user", "user", u.ID, "error", err)
|
|
continue
|
|
}
|
|
summaries = append(summaries, model.UserUsageSummary{
|
|
UserID: u.ID,
|
|
Usage: *usage,
|
|
})
|
|
}
|
|
writeJSON(w, http.StatusOK, summaries)
|
|
}
|
|
|
|
func (s *Server) handleBillingHistory(w http.ResponseWriter, r *http.Request) {
|
|
targetUser := chi.URLParam(r, "user")
|
|
|
|
if !canAccess(r, targetUser) {
|
|
writeError(w, http.StatusForbidden, "access denied")
|
|
return
|
|
}
|
|
|
|
if _, err := s.Users.GetUser(r.Context(), targetUser); err != nil {
|
|
if errors.Is(err, store.ErrNotFound) {
|
|
writeError(w, http.StatusNotFound, "user not found")
|
|
return
|
|
}
|
|
writeError(w, http.StatusInternalServerError, "failed to get user")
|
|
return
|
|
}
|
|
|
|
now := time.Now()
|
|
daily, err := s.Usage.GetDailyUsage(r.Context(), targetUser, now.Year(), now.Month())
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "failed to get usage history")
|
|
return
|
|
}
|
|
if daily == nil {
|
|
daily = []model.DailyUsage{}
|
|
}
|
|
writeJSON(w, http.StatusOK, daily)
|
|
}
|