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
87 lines
3.1 KiB
Go
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)
|
|
}
|
|
}
|