aboutsummaryrefslogtreecommitdiffstats
path: root/backend/cmd
diff options
context:
space:
mode:
authorLibravatarLibravatar Biswa Kalyan Bhuyan <biswa@surgot.in> 2025-04-24 08:18:27 +0530
committerLibravatarLibravatar Biswa Kalyan Bhuyan <biswa@surgot.in> 2025-04-24 08:18:27 +0530
commit50d5e6534f5e593297a09323e683c7c8b850117b (patch)
tree339d6e8b123c5d4caa4129971e2cb1b960b12a89 /backend/cmd
parent76066679b5bdab53419492066c4e80d2ed3be518 (diff)
downloadfinance-50d5e6534f5e593297a09323e683c7c8b850117b.tar.gz
finance-50d5e6534f5e593297a09323e683c7c8b850117b.tar.bz2
finance-50d5e6534f5e593297a09323e683c7c8b850117b.zip
feat: added basic backend features to it
- Set up API framework (Gin Gonic) - Set up ORM/DB library (GORM) - Design database schema (Users, Accounts, Transactions, Loans, Goals) - Set up database connection and migrations
Diffstat (limited to 'backend/cmd')
-rw-r--r--backend/cmd/api/main.go110
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)
+ }
+}