package handlers import ( "log" "net/http" "time" "github.com/Fimeg/RedFlag/aggregator-server/internal/database/queries" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/jmoiron/sqlx" ) // ScannerConfigHandler manages scanner timeout configuration type ScannerConfigHandler struct { queries *queries.ScannerConfigQueries } // NewScannerConfigHandler creates a new scanner config handler func NewScannerConfigHandler(db *sqlx.DB) *ScannerConfigHandler { return &ScannerConfigHandler{ queries: queries.NewScannerConfigQueries(db), } } // GetScannerTimeouts returns current scanner timeout configuration // GET /api/v1/admin/scanner-timeouts // Security: Requires admin authentication (WebAuthMiddleware) func (h *ScannerConfigHandler) GetScannerTimeouts(c *gin.Context) { configs, err := h.queries.GetAllScannerConfigs() if err != nil { log.Printf("[ERROR] Failed to fetch scanner configs: %v", err) c.JSON(http.StatusInternalServerError, gin.H{ "error": "failed to fetch scanner configuration", }) return } c.JSON(http.StatusOK, gin.H{ "scanner_timeouts": configs, "default_timeout_ms": 1800000, // 30 minutes default }) } // UpdateScannerTimeout updates scanner timeout configuration // PUT /api/v1/admin/scanner-timeouts/:scanner_name // Security: Requires admin authentication + audit logging func (h *ScannerConfigHandler) UpdateScannerTimeout(c *gin.Context) { scannerName := c.Param("scanner_name") if scannerName == "" { c.JSON(http.StatusBadRequest, gin.H{ "error": "scanner_name is required", }) return } var req struct { TimeoutMs int `json:"timeout_ms" binding:"required,min=1000,max=7200000"` // 1s to 2 hours } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } timeout := time.Duration(req.TimeoutMs) * time.Millisecond // Update config if err := h.queries.UpsertScannerConfig(scannerName, timeout); err != nil { log.Printf("[ERROR] Failed to update scanner config for %s: %v", scannerName, err) c.JSON(http.StatusInternalServerError, gin.H{ "error": "failed to update scanner configuration", }) return } // Create audit event in History table (ETHOS compliance) userID := c.MustGet("user_id").(uuid.UUID) /* event := &models.SystemEvent{ ID: uuid.New(), EventType: "scanner_config_change", EventSubtype: "timeout_updated", Severity: "info", Component: "admin_api", Message: fmt.Sprintf("Scanner timeout updated: %s = %v", scannerName, timeout), Metadata: map[string]interface{}{ "scanner_name": scannerName, "timeout_ms": req.TimeoutMs, "user_id": userID.String(), "source_ip": c.ClientIP(), }, CreatedAt: time.Now(), } // TODO: Integrate with event logging system when available */ log.Printf("[AUDIT] User %s updated scanner timeout: %s = %v", userID, scannerName, timeout) c.JSON(http.StatusOK, gin.H{ "message": "scanner timeout updated successfully", "scanner_name": scannerName, "timeout_ms": req.TimeoutMs, "timeout_human": timeout.String(), }) } // ResetScannerTimeout resets scanner timeout to default (30 minutes) // POST /api/v1/admin/scanner-timeouts/:scanner_name/reset // Security: Requires admin authentication + audit logging func (h *ScannerConfigHandler) ResetScannerTimeout(c *gin.Context) { scannerName := c.Param("scanner_name") if scannerName == "" { c.JSON(http.StatusBadRequest, gin.H{ "error": "scanner_name is required", }) return } defaultTimeout := 30 * time.Minute if err := h.queries.UpsertScannerConfig(scannerName, defaultTimeout); err != nil { log.Printf("[ERROR] Failed to reset scanner config for %s: %v", scannerName, err) c.JSON(http.StatusInternalServerError, gin.H{ "error": "failed to reset scanner configuration", }) return } // Audit log userID := c.MustGet("user_id").(uuid.UUID) log.Printf("[AUDIT] User %s reset scanner timeout: %s to default %v", userID, scannerName, defaultTimeout) c.JSON(http.StatusOK, gin.H{ "message": "scanner timeout reset to default", "scanner_name": scannerName, "timeout_ms": int(defaultTimeout.Milliseconds()), "timeout_human": defaultTimeout.String(), }) } // GetScannerConfigQueries provides access to the queries for config_builder.go func (h *ScannerConfigHandler) GetScannerConfigQueries() *queries.ScannerConfigQueries { return h.queries }