- Backend: Go API server with Gin framework - Frontend: React setup (placeholder) - ML Service: Python FastAPI skeleton - Docker Compose: Full stack configuration - Database: PostgreSQL schema with migrations - Documentation: Implementation plan and README Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
187 lines
6.1 KiB
Go
187 lines
6.1 KiB
Go
package api
|
|
|
|
import (
|
|
"database/sql"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/yourusername/victorialogs-manager/internal/config"
|
|
)
|
|
|
|
// NewRouter creates and configures the main router
|
|
func NewRouter(cfg *config.Config, db *sql.DB) *gin.Engine {
|
|
// Set Gin mode
|
|
gin.SetMode(gin.ReleaseMode)
|
|
|
|
router := gin.Default()
|
|
|
|
// CORS middleware
|
|
router.Use(corsMiddleware())
|
|
|
|
// Health check endpoint
|
|
router.GET("/health", func(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"status": "ok",
|
|
"service": "victorialogs-manager",
|
|
})
|
|
})
|
|
|
|
// API v1 routes
|
|
v1 := router.Group("/api/v1")
|
|
{
|
|
// Authentication routes (public)
|
|
auth := v1.Group("/auth")
|
|
{
|
|
auth.POST("/login", func(c *gin.Context) {
|
|
// TODO: Implement login handler
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
auth.POST("/refresh", func(c *gin.Context) {
|
|
// TODO: Implement refresh handler
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
auth.GET("/me", func(c *gin.Context) {
|
|
// TODO: Implement me handler (requires auth)
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
}
|
|
|
|
// Protected routes (require authentication)
|
|
// TODO: Add auth middleware here
|
|
|
|
// User management routes
|
|
users := v1.Group("/users")
|
|
{
|
|
users.GET("", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
users.POST("", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
users.GET("/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
users.PUT("/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
users.DELETE("/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
}
|
|
|
|
// Log querying routes
|
|
logs := v1.Group("/logs")
|
|
{
|
|
logs.POST("/query", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
logs.POST("/tail", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
logs.GET("/facets", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
logs.POST("/stats", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
logs.POST("/export", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
}
|
|
|
|
// Alert management routes
|
|
alerts := v1.Group("/alerts")
|
|
{
|
|
alerts.GET("/rules", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
alerts.POST("/rules", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
alerts.GET("/rules/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
alerts.PUT("/rules/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
alerts.DELETE("/rules/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
alerts.POST("/reload", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
alerts.GET("/active", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
}
|
|
|
|
// Pattern detection routes
|
|
patterns := v1.Group("/patterns")
|
|
{
|
|
patterns.GET("", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
patterns.POST("", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
patterns.PUT("/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
patterns.DELETE("/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
patterns.POST("/detect", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
patterns.POST("/ml/train", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
patterns.POST("/ml/detect", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
}
|
|
|
|
// Report routes
|
|
reports := v1.Group("/reports")
|
|
{
|
|
reports.GET("", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
reports.POST("", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
reports.GET("/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
reports.PUT("/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
reports.DELETE("/:id", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
reports.POST("/:id/execute", func(c *gin.Context) {
|
|
c.JSON(http.StatusNotImplemented, gin.H{"message": "not implemented yet"})
|
|
})
|
|
}
|
|
}
|
|
|
|
return router
|
|
}
|
|
|
|
// corsMiddleware handles CORS headers
|
|
func corsMiddleware() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
|
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
|
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
|
|
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
|
|
|
|
if c.Request.Method == "OPTIONS" {
|
|
c.AbortWithStatus(204)
|
|
return
|
|
}
|
|
|
|
c.Next()
|
|
}
|
|
}
|