imc-vibe/backend/internal/api/router.go
Christoph Haas 269fb6f53a Security fixes
1. Password reset tokens: use crypto/rand instead of math/rand
2. IP spoofing: only trust X-Forwarded-For from configured trusted proxies
3. Cleanup: purge failed login attempts older than 24 hours
4. JWT secret: validate minimum 32 character length on startup

Updated .env.example with TRUSTED_PROXIES setting
2026-03-23 01:09:26 +01:00

87 lines
3.1 KiB
Go

package api
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/imc-vibe/backend/internal/api/handlers"
"github.com/imc-vibe/backend/internal/auth"
"github.com/imc-vibe/backend/internal/config"
"github.com/imc-vibe/backend/internal/db"
"github.com/imc-vibe/backend/internal/mail"
)
type Router struct {
authHandler *handlers.AuthHandler
domainHandler *handlers.DomainHandler
userHandler *handlers.UserHandler
aliasHandler *handlers.AliasHandler
statsHandler *handlers.StatsHandler
queueHandler *handlers.QueueHandler
logsHandler *handlers.LogsHandler
jwtManager *auth.JWTManager
}
func New(database *db.DB, cfg *config.Config) *Router {
jwtManager := auth.NewJWTManager(cfg.JWTSecret, "imc-vibe")
emailService := mail.NewEmailService(cfg)
r := &Router{
authHandler: handlers.NewAuthHandler(database, jwtManager, emailService, cfg.TrustedProxies),
domainHandler: handlers.NewDomainHandler(database),
userHandler: handlers.NewUserHandler(database),
aliasHandler: handlers.NewAliasHandler(database),
statsHandler: handlers.NewStatsHandler(database),
queueHandler: handlers.NewQueueHandler(),
logsHandler: handlers.NewLogsHandler(),
jwtManager: jwtManager,
}
return r
}
func (r *Router) RegisterRoutes(engine *gin.Engine) {
engine.GET("/api/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok"})
})
engine.POST("/api/auth/login", r.authHandler.Login)
engine.POST("/api/auth/forgot", r.authHandler.ForgotPassword)
engine.POST("/api/auth/logout", r.authHandler.Logout)
authGroup := engine.Group("/api")
authGroup.Use(handlers.AuthMiddleware(r.jwtManager))
{
authGroup.GET("/auth/me", r.authHandler.Me)
authGroup.POST("/auth/change-password", r.authHandler.ChangePassword)
authGroup.GET("/stats", r.statsHandler.Get)
authGroup.GET("/domains", r.domainHandler.List)
authGroup.POST("/domains", r.domainHandler.Create)
authGroup.DELETE("/domains/:name", r.domainHandler.Delete)
authGroup.GET("/domains/:name", r.domainHandler.Get)
authGroup.GET("/domains/:name/users", r.userHandler.List)
authGroup.GET("/domains/:name/users/:id", r.userHandler.Get)
authGroup.POST("/domains/:name/users", r.userHandler.Create)
authGroup.PUT("/domains/:name/users/:id", r.userHandler.Update)
authGroup.DELETE("/domains/:name/users/:id", r.userHandler.Delete)
authGroup.GET("/domains/:name/aliases", r.aliasHandler.List)
authGroup.POST("/domains/:name/aliases", r.aliasHandler.Create)
authGroup.DELETE("/domains/:name/aliases/:id", r.aliasHandler.Delete)
authGroup.GET("/queue", r.queueHandler.List)
authGroup.POST("/queue/:id/requeue", r.queueHandler.Requeue)
authGroup.DELETE("/queue/:id", r.queueHandler.Delete)
authGroup.GET("/logs", r.logsHandler.List)
}
adminGroup := engine.Group("/api/admin")
adminGroup.Use(handlers.AuthMiddleware(r.jwtManager), handlers.RequireAdmin())
{
adminGroup.GET("/domains/:name/permissions", r.domainHandler.GetPermissions)
adminGroup.POST("/domains/:name/permissions", r.domainHandler.AddPermission)
adminGroup.DELETE("/domains/:name/permissions/:userId", r.domainHandler.RemovePermission)
}
}