package server import ( "encoding/json" "net/http" "strconv" ) // GET /api/v1/admin/audit?tenant=3&limit=50&offset=0&action=node_kick&actor_type=session&actor_id=12&target_type=node&target_id=nodeA&from=1700000000&to=1700003600 func (s *Server) HandleAdminAudit(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } limit := 50 offset := 0 if v := r.URL.Query().Get("limit"); v != "" { if i, err := strconv.Atoi(v); err == nil && i > 0 && i <= 500 { limit = i } } if v := r.URL.Query().Get("offset"); v != "" { if i, err := strconv.Atoi(v); err == nil && i >= 0 { offset = i } } tenantID := int64(0) if v := r.URL.Query().Get("tenant"); v != "" { if i, err := strconv.ParseInt(v, 10, 64); err == nil { tenantID = i } } action := r.URL.Query().Get("action") actorType := r.URL.Query().Get("actor_type") actorID := r.URL.Query().Get("actor_id") targetType := r.URL.Query().Get("target_type") targetID := r.URL.Query().Get("target_id") fromTs := int64(0) toTs := int64(0) if v := r.URL.Query().Get("from"); v != "" { if i, err := strconv.ParseInt(v, 10, 64); err == nil && i > 0 { fromTs = i } } if v := r.URL.Query().Get("to"); v != "" { if i, err := strconv.ParseInt(v, 10, 64); err == nil && i > 0 { toTs = i } } logs, err := s.store.ListAuditLogs(tenantID, limit, offset, action, actorType, actorID, targetType, targetID, fromTs, toTs) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(map[string]any{"error": 0, "logs": logs}) }