Files
NewSmoop/server/internal/router/router.go

104 lines
3.9 KiB
Go

package router
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/minio/minio-go/v7"
"gorm.io/gorm"
"smoop-api/internal/config"
"smoop-api/internal/crypto"
"smoop-api/internal/handlers"
"smoop-api/internal/middleware"
)
func Build(db *gorm.DB, minio *minio.Client, cfg *config.Config) *gin.Engine {
r := gin.Default()
jwtMgr := crypto.NewJWT(cfg.JWTSecret)
// --- Handlers
authH := handlers.NewAuthHandler(db, jwtMgr)
usersH := handlers.NewUsersHandler(db)
devH := handlers.NewDevicesHandler(db)
recH := handlers.NewRecordsHandler(db, minio, cfg.MinIO.RecordsBucket, cfg.MinIO.PresignTTL)
liveH := handlers.NewLivestreamHandler(minio, cfg.MinIO.LivestreamBucket)
// --- MediaMTX handler
mediamtxH := handlers.NewMediaMTXHandler(db, jwtMgr, cfg.MediaMTX)
/// --- GPS tracker handler
trackersH := handlers.NewTrackersHandler(db)
tasksH := handlers.NewTasksHandler(db)
certsH := handlers.NewCertsHandler(db, &cfg.PkiIot, "720h")
certsAdminH := handlers.NewCertsAdminHandler(db, &cfg.PkiIot)
// --- Public auth
r.POST("/auth/signup", authH.SignUp)
r.POST("/auth/signin", authH.SignIn)
r.POST("/auth/check_token", authH.CheckToken)
// Protected
authMW := handlers.Auth(jwtMgr)
adminOnly := handlers.RequireRole("admin")
r.POST("/auth/change_password", authMW, authH.ChangePassword)
r.GET("/users/profile", authMW, usersH.Profile)
r.POST("/users/:id/set_role", authMW, adminOnly, usersH.SetRole)
r.GET("/users", authMW, adminOnly, usersH.List)
r.POST("/users/create", authMW, adminOnly, usersH.Create)
r.DELETE("/users/:id", authMW, adminOnly, usersH.Delete)
r.GET("/devices", authMW, middleware.DeviceAccessFilter(), devH.List)
r.POST("/devices/create", authMW, adminOnly, devH.Create)
r.POST("/devices/:guid/rename", authMW, devH.Rename)
r.POST("/devices/:guid/add_to_user", authMW, devH.AddToUser)
r.POST("/devices/:guid/set_users", authMW, adminOnly, devH.SetUsers)
r.POST("/devices/:guid/remove_from_user", authMW, devH.RemoveFromUser)
r.POST("/device/:guid/task", authMW, middleware.DeviceAccessFilter(), tasksH.CreateTask)
r.GET("/device/:guid/tasks", authMW, middleware.DeviceAccessFilter(), tasksH.ListDeviceTasks)
r.GET("/device/:guid/certs", authMW, adminOnly, devH.ListCertsByDevice)
r.POST("/certs/revoke", authMW, adminOnly, certsAdminH.Revoke)
r.POST("/records/upload", middleware.MTLSGuardUpload(db), recH.Upload)
r.GET("/records", authMW, recH.List)
r.GET("/records/:id/file", authMW, recH.File)
// WebSocket livestream
r.GET("/livestream", authMW, liveH.Upgrade)
// health
r.GET("/healthz", func(c *gin.Context) { c.String(http.StatusOK, "ok") })
// --- NEW: MediaMTX integration routes
// External auth (called by MediaMTX)
r.POST("/mediamtx/auth", mediamtxH.Auth)
// Token minting for device/user flows
r.POST("/mediamtx/token/publish", mediamtxH.MintPublish)
r.POST("/mediamtx/token/read", authMW, mediamtxH.MintRead)
// Admin controls
r.GET("/mediamtx/paths", authMW, adminOnly, mediamtxH.ListPaths)
r.POST("/mediamtx/webrtc/kick/:id", authMW, adminOnly, mediamtxH.KickWebRTC)
r.GET("/trackers", authMW, middleware.TrackerAccessFilter(), trackersH.List)
r.POST("/trackers/create", authMW, trackersH.Create)
r.POST("/trackers/:guid/rename", authMW, trackersH.Rename)
r.POST("/trackers/:guid/set_users", authMW, adminOnly, trackersH.SetUsers)
// --- Device Job/Task API
r.GET("/tasks/:guid", middleware.MTLSGuard(db), tasksH.DeviceNextTask) // heartbeat + fetch next task
r.POST("/tasks/:guid", middleware.MTLSGuard(db), tasksH.DevicePostResult) // device posts result
r.POST("/enroll/:guid", certsH.Enroll) // simple device-exists check is inside handler
r.POST("/renew/:guid", middleware.MTLSGuard(db), certsH.Renew)
// sensible defaults
r.MaxMultipartMemory = 64 << 20 // 64 MiB
_ = time.Now() // appease linters
return r
}
// --- JWT middleware & helpers (kept here to avoid new dirs) ---