initial: ZeroTier-like P2P mesh VPN server with multi-tenant Web UI
This commit is contained in:
124
internal/router/router.go
Normal file
124
internal/router/router.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"zeromesh/internal/config"
|
||||
"zeromesh/internal/database"
|
||||
"zeromesh/internal/handler"
|
||||
"zeromesh/internal/middleware"
|
||||
"zeromesh/internal/repository"
|
||||
"zeromesh/internal/service"
|
||||
)
|
||||
|
||||
func Setup(cfg *config.Config, db *database.DB) *gin.Engine {
|
||||
r := gin.Default()
|
||||
|
||||
// Repositories
|
||||
userRepo := repository.NewUserRepo(db)
|
||||
netRepo := repository.NewNetworkRepo(db)
|
||||
nodeRepo := repository.NewNodeRepo(db)
|
||||
logRepo := repository.NewLogRepo(db)
|
||||
|
||||
// Services
|
||||
authService := service.NewAuthService(userRepo, cfg.JWT)
|
||||
netService := service.NewNetworkService(netRepo, nodeRepo, userRepo)
|
||||
nodeService := service.NewNodeService(nodeRepo, userRepo)
|
||||
logService := service.NewLogService(logRepo)
|
||||
|
||||
// Global middleware
|
||||
r.Use(middleware.CORS(cfg.CORS.AllowedOrigins))
|
||||
if cfg.RateLimit.Enabled {
|
||||
rl := middleware.NewRateLimiter(cfg.RateLimit.RequestsPerSecond, cfg.RateLimit.BurstSize)
|
||||
r.Use(rl.Handler())
|
||||
}
|
||||
requestLogger := middleware.NewRequestLogger(logService)
|
||||
r.Use(requestLogger.Handler())
|
||||
|
||||
// Handlers
|
||||
authHandler := handler.NewAuthHandler(authService)
|
||||
netHandler := handler.NewNetworkHandler(netService)
|
||||
nodeHandler := handler.NewNodeHandler(nodeService)
|
||||
adminHandler := handler.NewAdminHandler(authService, db, nodeService, netService)
|
||||
logHandler := handler.NewLogHandler(logService)
|
||||
|
||||
// Logging API — skip logger middleware (avoid recursion)
|
||||
logApi := r.Group("/api/v1/log")
|
||||
logApi.Use(middleware.JWTAuth(cfg.JWT.Secret))
|
||||
{
|
||||
logApi.GET("/api", logHandler.ListApiLogs)
|
||||
logApi.GET("/error", logHandler.ListErrorLogs)
|
||||
logApi.GET("/grouped", logHandler.ListApiLogGrouped)
|
||||
logApi.DELETE("/api", logHandler.ClearApiLogs)
|
||||
logApi.DELETE("/error", logHandler.ClearErrorLogs)
|
||||
}
|
||||
|
||||
// Public routes
|
||||
r.GET("/api/health", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{"status": "ok"})
|
||||
})
|
||||
r.GET("/api/v1/admin/check", authHandler.CheckAdmin)
|
||||
|
||||
api := r.Group("/api/v1")
|
||||
{
|
||||
api.POST("/auth/login", authHandler.Login)
|
||||
api.POST("/auth/register", authHandler.Register)
|
||||
api.POST("/auth/init", authHandler.InitAdmin)
|
||||
}
|
||||
|
||||
// Authenticated routes
|
||||
auth := r.Group("/api/v1")
|
||||
auth.Use(middleware.JWTAuth(cfg.JWT.Secret))
|
||||
{
|
||||
// Dashboard (user + admin)
|
||||
auth.GET("/dashboard", adminHandler.Dashboard)
|
||||
|
||||
// Profile
|
||||
auth.GET("/user/profile", func(c *gin.Context) {
|
||||
uid := c.GetUint("user_id")
|
||||
u, err := userRepo.FindByID(uid)
|
||||
if err != nil {
|
||||
c.JSON(404, gin.H{"error": "user not found"})
|
||||
return
|
||||
}
|
||||
netCount, _ := netRepo.CountByUser(uid)
|
||||
nodeCount, _ := nodeRepo.CountByUser(uid)
|
||||
c.JSON(200, gin.H{
|
||||
"user": u,
|
||||
"used_networks": netCount,
|
||||
"used_nodes": nodeCount,
|
||||
})
|
||||
})
|
||||
|
||||
// Nodes (user-scoped)
|
||||
auth.POST("/node/register", nodeHandler.Register)
|
||||
auth.GET("/node/list", nodeHandler.List)
|
||||
auth.GET("/node/online", nodeHandler.ListOnline)
|
||||
|
||||
// Networks (user-scoped)
|
||||
auth.POST("/network/create", netHandler.Create)
|
||||
auth.GET("/network/list", netHandler.List)
|
||||
auth.GET("/network/:id", netHandler.Get)
|
||||
auth.DELETE("/network/:id", netHandler.Delete)
|
||||
auth.GET("/network/:id/members", netHandler.Members)
|
||||
auth.POST("/network/:id/authorize", netHandler.Authorize)
|
||||
auth.POST("/network/:id/deauthorize", netHandler.Deauthorize)
|
||||
|
||||
// Admin-only
|
||||
admin := auth.Group("/admin")
|
||||
admin.Use(func(c *gin.Context) {
|
||||
if c.GetString("role") != "admin" {
|
||||
c.AbortWithStatusJSON(403, gin.H{"error": "forbidden"})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
})
|
||||
{
|
||||
admin.GET("/dashboard", adminHandler.Dashboard)
|
||||
admin.GET("/networks", netHandler.List)
|
||||
admin.GET("/nodes", nodeHandler.List)
|
||||
}
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
Reference in New Issue
Block a user