package router import ( "finance/backend/internal/api/handlers" "finance/backend/internal/config" "finance/backend/internal/database" "net/http" "github.com/gin-gonic/gin" ) // SetupRouter configures the API routes func SetupRouter(cfg *config.Config) *gin.Engine { r := gin.Default() // Enable CORS r.Use(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() }) // Public utility endpoints r.GET("/ping", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "pong", }) }) // Add database status endpoint r.GET("/db-status", func(c *gin.Context) { // Try to get a connection from the pool sqlDB, err := database.DB.DB() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "status": "error", "message": "Failed to get database connection", "error": err.Error(), }) return } // Check if database is reachable err = sqlDB.Ping() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "status": "error", "message": "Database is not reachable", "error": err.Error(), }) return } c.JSON(http.StatusOK, gin.H{ "status": "success", "message": "Database connection is healthy", }) }) // Initialize handlers authHandler := handlers.NewAuthHandler(cfg) goalHandler := handlers.NewGoalHandler() userHandler := handlers.NewUserHandler() accountHandler := handlers.NewAccountHandler() transactionHandler := handlers.NewTransactionHandler() loanHandler := handlers.NewLoanHandler() // API v1 routes v1 := r.Group("/api/v1") { // Auth routes (public) v1.POST("/auth/signup", authHandler.Register) v1.POST("/auth/login", authHandler.Login) // Protected routes protected := v1.Group("") protected.Use(authHandler.JWTAuth) { // User routes protected.GET("/users/me", userHandler.GetCurrentUser) protected.PUT("/users/me", userHandler.UpdateCurrentUser) // Account routes protected.GET("/accounts", accountHandler.GetAccounts) protected.GET("/accounts/:id", accountHandler.GetAccountByID) protected.POST("/accounts", accountHandler.CreateAccount) protected.PUT("/accounts/:id", accountHandler.UpdateAccount) protected.DELETE("/accounts/:id", accountHandler.DeleteAccount) // Transaction routes protected.GET("/transactions", transactionHandler.GetTransactions) protected.GET("/transactions/:id", transactionHandler.GetTransactionByID) protected.POST("/transactions", transactionHandler.CreateTransaction) protected.PUT("/transactions/:id", transactionHandler.UpdateTransaction) protected.DELETE("/transactions/:id", transactionHandler.DeleteTransaction) // Goal routes protected.GET("/goals", goalHandler.GetGoals) protected.GET("/goals/:id", goalHandler.GetGoal) protected.POST("/goals", goalHandler.CreateGoal) protected.PUT("/goals/:id", goalHandler.UpdateGoal) protected.DELETE("/goals/:id", goalHandler.DeleteGoal) protected.PATCH("/goals/:id/progress", goalHandler.UpdateGoalProgress) // New Goal Progress Tracking routes protected.GET("/goals/:id/progress", goalHandler.GetGoalProgressDetails) protected.GET("/goals/progress/all", goalHandler.GetAllGoalsProgressDetails) protected.POST("/goals/:id/link-transaction", goalHandler.LinkTransactionToGoal) protected.POST("/goals/:id/recalculate", goalHandler.RecalculateGoalProgress) // Loan routes protected.GET("/loans", loanHandler.GetLoans) protected.GET("/loans/:id", loanHandler.GetLoanByID) protected.POST("/loans", loanHandler.CreateLoan) protected.PUT("/loans/:id", loanHandler.UpdateLoan) protected.DELETE("/loans/:id", loanHandler.DeleteLoan) } } return r }