accounts/api/admin_users_metrics.go
Haitao Pan 07e31ff6bd feat: move account service to repo root
# Conflicts:
#	account/Makefile
#	account/go.mod
#	docs/account-admin-settings.md
#	docs/account-svc-plus.md
2026-01-16 16:15:23 +08:00

90 lines
2.3 KiB
Go

package api
import (
"errors"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"account/internal/service"
"account/internal/store"
)
func (h *handler) adminUsersMetrics(c *gin.Context) {
if h.metricsProvider == nil {
respondError(c, http.StatusServiceUnavailable, "metrics_unavailable", "user metrics provider is not configured")
return
}
if _, ok := h.requireAdminOrOperator(c); !ok {
return
}
metrics, err := h.metricsProvider.Compute(c.Request.Context())
if err != nil {
status := http.StatusInternalServerError
message := "failed to compute user metrics"
if errors.Is(err, service.ErrUserRepositoryNotConfigured) || errors.Is(err, service.ErrSubscriptionProviderNotConfigured) {
status = http.StatusServiceUnavailable
message = "user metrics dependency is not available"
}
respondError(c, status, "metrics_unavailable", message)
return
}
c.JSON(http.StatusOK, metrics)
}
func (h *handler) requireAdminOrOperator(c *gin.Context) (*store.User, bool) {
token := h.resolveSessionToken(c)
if token == "" {
respondError(c, http.StatusUnauthorized, "session_token_required", "session token is required")
return nil, false
}
sess, ok := h.lookupSession(token)
if !ok {
respondError(c, http.StatusUnauthorized, "invalid_session", "session not found or expired")
return nil, false
}
user, err := h.store.GetUserByID(c.Request.Context(), sess.userID)
if err != nil {
respondError(c, http.StatusInternalServerError, "session_user_lookup_failed", "failed to load session user")
return nil, false
}
role := strings.ToLower(strings.TrimSpace(user.Role))
if role != store.RoleAdmin && role != store.RoleOperator {
respondError(c, http.StatusForbidden, "forbidden", "insufficient permissions")
return nil, false
}
return user, true
}
func (h *handler) resolveSessionToken(c *gin.Context) string {
token := extractToken(c.GetHeader("Authorization"))
if token == "" {
if value := c.Query("token"); value != "" {
token = value
}
}
if token == "" {
if cookie, err := c.Cookie(sessionCookieName); err == nil {
cookie = strings.TrimSpace(cookie)
if cookie != "" {
token = cookie
}
}
}
return strings.TrimSpace(token)
}
func registerAdminRoutes(group *gin.RouterGroup, h *handler) {
admin := group.Group("/admin")
admin.GET("/users/metrics", h.adminUsersMetrics)
admin.GET("/agents/status", h.adminAgentStatus)
}