diff options
Diffstat (limited to 'backend/cmd/api/main.go')
-rw-r--r-- | backend/cmd/api/main.go | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/backend/cmd/api/main.go b/backend/cmd/api/main.go new file mode 100644 index 0000000..de021fa --- /dev/null +++ b/backend/cmd/api/main.go @@ -0,0 +1,110 @@ +package main + +import ( + "log" + "net/http" + + "finance/backend/internal/api/auth" + "finance/backend/internal/api/v1/loans" + "finance/backend/internal/config" + "finance/backend/internal/database" + + "github.com/gin-gonic/gin" +) + +func main() { + // Load Configuration + cfg, err := config.LoadConfig() + if err != nil { + log.Fatalf("Failed to load configuration: %v", err) + } + + // Initialize Database + if err := database.InitDatabase(cfg); err != nil { + log.Fatalf("Failed to initialize database: %v", err) + } + + // Setup Gin Router + r := gin.Default() + + // 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", + }) + }) + + // API v1 routes + v1 := r.Group("/api/v1") + { + // Auth routes (public) + v1.POST("/auth/signup", auth.Signup(cfg)) + v1.POST("/auth/login", auth.Login(cfg)) + + // Protected routes + protected := v1.Group("") + protected.Use(auth.AuthMiddleware(cfg)) + { + // User routes + protected.GET("/users/me", func(c *gin.Context) { + // Get user from context (set by auth middleware) + user, exists := c.Get("user") + if !exists { + c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) + return + } + + c.JSON(http.StatusOK, gin.H{"user": user}) + }) + + // Loan routes + loanRoutes := protected.Group("/loans") + { + loanRoutes.GET("", loans.GetLoans()) + loanRoutes.GET("/:id", loans.GetLoanByID()) + loanRoutes.POST("", loans.CreateLoan()) + loanRoutes.PUT("/:id", loans.UpdateLoan()) + loanRoutes.DELETE("/:id", loans.DeleteLoan()) + } + } + } + + // Run the server + serverAddr := ":8080" // TODO: Make this configurable via cfg + log.Printf("Starting server on %s", serverAddr) + err = r.Run(serverAddr) + if err != nil { + // Use Fatalf to exit if server fails to start + log.Fatalf("Failed to start server: %v", err) + } +} |