From 811a54799bb1879785ecdddde9200939e02eb65a Mon Sep 17 00:00:00 2001 From: pantorn Date: Fri, 4 Apr 2025 03:12:18 +0700 Subject: [PATCH 01/11] fix oauth --- backend/.env.example | 13 ++++ backend/.gitignore | 1 + backend/api/index.go | 51 +++++++++++++++ backend/config/config.go | 22 ++----- backend/config/database.go | 15 ++--- backend/controllers/auth_controller.go | 10 +-- backend/controllers/github.go | 13 ++-- backend/controllers/google.go | 40 ++++++++---- backend/go.mod | 12 +--- backend/go.sum | 87 ------------------------- backend/handlers/budget_handler.go | 4 +- backend/handlers/category_handler.go | 4 +- backend/handlers/plan_handler.go | 6 +- backend/handlers/transaction_handler.go | 4 +- backend/handlers/user_handler.go | 21 +++--- backend/main.go | 59 ----------------- backend/middleware/cors_middleware.go | 13 ++-- backend/models/plan.go | 29 ++++----- backend/routes/auth_routes.go | 2 +- backend/routes/oauth_routes.go | 4 +- backend/routes/routes.go | 8 +-- backend/routes/ws.go | 76 --------------------- backend/vercel.json | 5 ++ 23 files changed, 172 insertions(+), 327 deletions(-) create mode 100644 backend/.env.example create mode 100644 backend/.gitignore create mode 100644 backend/api/index.go delete mode 100644 backend/main.go delete mode 100644 backend/routes/ws.go create mode 100644 backend/vercel.json diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..cbf035d --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,13 @@ +GOOGLE_CLIENT_ID=your_google_client_id_here +GOOGLE_CLIENT_SECRET=your_google_client_secret_here +GITHUB_CLIENT_ID=your_github_client_id_here +GITHUB_CLIENT_SECRET=your_github_client_secret_here +jwtSecretKey=your_jwtsecretkey_here +DB_HOST=your_db_host_here +DB_USER=your_db_user_here +DB_PASSWORD=your_db_password_here +DB_NAME=your_db_name_here +DB_PORT=your_db_port_here +FRONTEND_URL=your_frontend_url_here +# FRONTEND_URL : http://cashwise.com +FRONTEND_URL=your_frontend_url_here diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..e985853 --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1 @@ +.vercel diff --git a/backend/api/index.go b/backend/api/index.go new file mode 100644 index 0000000..cc47fd8 --- /dev/null +++ b/backend/api/index.go @@ -0,0 +1,51 @@ +package handler + +import ( + "net/http" + + // "os" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/adaptor" + + // jwtware "github.com/gofiber/jwt/v3" + + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/middleware" + "github.com/long104/SenZen/routes" +) + +// Handler is the main entry point of the application. +func Handler(w http.ResponseWriter, r *http.Request) { + // Set the proper request path in `*fiber.Ctx` + r.RequestURI = r.URL.String() + handler().ServeHTTP(w, r) +} +func handler() http.HandlerFunc { + config.ConnectDatabase() + app := fiber.New() + + app.Use(middleware.CORSMiddleware()) + + app.Get("api/health", func(c *fiber.Ctx) error { + return c.SendString("health check ok") + }) + + routes.SetupOAuthRoutes(app) + routes.SetupAuthRoutes(app) + + // app.Use(jwtware.New(jwtware.Config{ + // SigningKey: []byte(os.Getenv("jwtSecretKey")), + // })) + + // app.Use("/admin", middleware.checkMiddleware) + // app.Use("/books", AuthRequired) + app.Get("api/validate-token", middleware.ValidateToken) + + routes.SetupRoutes(app) + + // setupRoutes(app) + + // app.Listen(":8080") + return adaptor.FiberApp(app) +} diff --git a/backend/config/config.go b/backend/config/config.go index 6f6d6ff..a150f5b 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -1,11 +1,9 @@ package config import ( - "log" "os" - // "fmt" - "github.com/joho/godotenv" + // "fmt" "golang.org/x/oauth2" "golang.org/x/oauth2/github" "golang.org/x/oauth2/google" @@ -19,14 +17,9 @@ type Config struct { var AppConfig Config func GoogleConfig() oauth2.Config { - err := godotenv.Load(".env") - if err != nil { - log.Fatalf("Some error occured. Err: %s", err) - } - AppConfig.GoogleLoginConfig = oauth2.Config{ - RedirectURL: "http://localhost:8080/google_callback", - // RedirectURL: "http://localhost:3000/", + // RedirectURL: "http://localhost:8080/google_callback", + RedirectURL: "https://senzen-backend.vercel.app/google_callback", ClientID: os.Getenv("GOOGLE_CLIENT_ID"), ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), Scopes: []string{ @@ -40,14 +33,9 @@ func GoogleConfig() oauth2.Config { } func GithubConfig() oauth2.Config { - err := godotenv.Load(".env") - if err != nil { - log.Fatalf("Some error occured. Err: %s", err) - } - AppConfig.GitHubLoginConfig = oauth2.Config{ - RedirectURL: "http://localhost:8080/github_callback", - // RedirectURL: "http://localhost:3000/", + // RedirectURL: "http://localhost:8080/github_callback", + RedirectURL: "https://senzen-backend.vercel.app/google_callback", ClientID: os.Getenv("GITHUB_CLIENT_ID"), // RedirectURL: fmt.Sprintf( // "https://github.com/login/oauth/authorize?scope=user:repo&client_id=%s&redirect_uri=%s", os.Getenv("GITHUB_CLIENT_ID"), "http://localhost:8080/github_callback"), diff --git a/backend/config/database.go b/backend/config/database.go index bdff166..3653bc7 100644 --- a/backend/config/database.go +++ b/backend/config/database.go @@ -7,7 +7,7 @@ import ( "os" "time" - "github.com/long104/CashWise/models" // Adjust this import path to match your project structure + "github.com/long104/SenZen/models" // Adjust this import path to match your project structure "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -17,12 +17,11 @@ var DB *gorm.DB // ConnectDatabase initializes the database connection. func ConnectDatabase() { - // Set up the DSN and GORM logger - dsn := fmt.Sprintf( - "host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Bangkok", - os.Getenv("DB_HOST"), os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), os.Getenv("DB_PORT"), - ) + // dsn := fmt.Sprintf( + // "host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Bangkok", + // os.Getenv("DB_HOST"), os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), os.Getenv("DB_PORT"), + // ) newLogger := logger.New( log.New(os.Stdout, "\r\n", log.LstdFlags), @@ -33,10 +32,10 @@ func ConnectDatabase() { }, ) - var err error + var err error // Connect to the database - DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{Logger: newLogger}) + DB, err = gorm.Open(postgres.Open(os.Getenv("DATABASE_URL")), &gorm.Config{Logger: newLogger}) if err != nil { log.Fatalf("failed to connect to database: %v", err) } diff --git a/backend/controllers/auth_controller.go b/backend/controllers/auth_controller.go index 1b632de..b9748c8 100644 --- a/backend/controllers/auth_controller.go +++ b/backend/controllers/auth_controller.go @@ -7,8 +7,8 @@ import ( "github.com/gofiber/fiber/v2" "github.com/golang-jwt/jwt/v4" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/models" + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/models" "golang.org/x/crypto/bcrypt" ) @@ -71,9 +71,9 @@ func LoginUser(c *fiber.Ctx) error { // Set cookie c.Cookie(&fiber.Cookie{ - Name: "jwt", - Value: t, - Path: "/", + Name: "jwt", + Value: t, + Path: "/", // Domain: "cashwise.com", Expires: time.Now().Add(time.Hour * 72), // HTTPOnly: true, diff --git a/backend/controllers/github.go b/backend/controllers/github.go index 6a2cf46..1159d5d 100644 --- a/backend/controllers/github.go +++ b/backend/controllers/github.go @@ -1,5 +1,4 @@ package controllers - import ( "context" "encoding/json" @@ -12,8 +11,8 @@ import ( "github.com/gofiber/fiber/v2" "github.com/golang-jwt/jwt/v4" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/models" + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/models" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -36,8 +35,7 @@ func GithubCallback(c *fiber.Ctx) error { Colorful: true, // Enable color }, ) - dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Bangkok", os.Getenv("DB_HOST"), os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), os.Getenv("DB_PORT")) - db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{Logger: newLogger}) + db, err := gorm.Open(postgres.Open(os.Getenv("DATABASE_URL")), &gorm.Config{Logger: newLogger}) if err != nil { panic("failed to connect to database") } @@ -128,9 +126,10 @@ func GithubCallback(c *fiber.Ctx) error { Name: "jwt", Value: t, Path: "/", - Domain: "cashwise.com", + // Domain: "cashwise.com", + Domain: "https://senzen-frontend.vercel.app", Expires: time.Now().Add(time.Hour * 72), - Secure: false, + // Secure: false, // HTTPOnly: true, HTTPOnly: false, SameSite: "Lax", diff --git a/backend/controllers/google.go b/backend/controllers/google.go index 93db8fa..85088a5 100644 --- a/backend/controllers/google.go +++ b/backend/controllers/google.go @@ -12,8 +12,8 @@ import ( "github.com/gofiber/fiber/v2" "github.com/golang-jwt/jwt/v4" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/models" + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/models" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -36,8 +36,7 @@ func GoogleCallback(c *fiber.Ctx) error { Colorful: true, // Enable color }, ) - dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Bangkok", os.Getenv("DB_HOST"), os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), os.Getenv("DB_PORT")) - db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{Logger: newLogger}) + db, err := gorm.Open(postgres.Open(os.Getenv("DATABASE_URL")), &gorm.Config{Logger: newLogger}) if err != nil { panic("failed to connect to database") } @@ -46,7 +45,6 @@ func GoogleCallback(c *fiber.Ctx) error { if state != "randomstate" { return c.SendString("States don't Match!!") } - code := c.Query("code") googlecon := config.GoogleConfig() @@ -101,15 +99,30 @@ func GoogleCallback(c *fiber.Ctx) error { } // Create a new user - db.Create(&models.User{Name: userName, Email: userEmail}) + result := db.Create(&models.User{Name: userName, Email: userEmail}) + if result.Error != nil { + return c.JSON(map[string]any{ + "Status": http.StatusInternalServerError, + "Error": result.Error, + }) + } + + + + var userDatabase models.User res := db.Where("email = ?", userEmail).First(&userDatabase) if res.RowsAffected == 0 { - db.Create(&models.User{Name: userName, Email: userEmail}) - } + result := db.Create(&models.User{Name: userName, Email: userEmail}) + if result.Error != nil { + return c.JSON(map[string]any{ + "Status": http.StatusInternalServerError, + "Error": result.Error, + }) + } } appToken := jwt.New(jwt.SigningMethodHS256) claims := appToken.Claims.(jwt.MapClaims) @@ -119,24 +132,29 @@ func GoogleCallback(c *fiber.Ctx) error { claims["role"] = "admin" claims["name"] = userName claims["email"] = userEmail - - // claims["role"] = "memeber" +// claims["role"] = "memeber" t, err := appToken.SignedString([]byte(os.Getenv("jwtSecretKey"))) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } + // Set cookie c.Cookie(&fiber.Cookie{ Name: "jwt", Value: t, + // Path: "/", Expires: time.Now().Add(time.Hour * 72), // HTTPOnly: true, - HTTPOnly: false, + // Domain: "https://senzen-frontend.vercel.app", + Secure: false, + SameSite: "Lax", }) // return c.SendString(string(userData)) // return c.Redirect("http://localhost:3000/home") + + fmt.Print("ip is ",c.IP()) return c.Redirect(os.Getenv("FRONTEND_URL") + "/home") } diff --git a/backend/go.mod b/backend/go.mod index 7cd8d9c..07566ba 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -1,10 +1,11 @@ -module github.com/long104/CashWise +module github.com/long104/SenZen go 1.22.7 require ( github.com/gofiber/fiber/v2 v2.52.5 - github.com/joho/godotenv v1.5.1 + github.com/golang-jwt/jwt/v4 v4.5.0 + golang.org/x/crypto v0.29.0 golang.org/x/oauth2 v0.23.0 gorm.io/driver/postgres v1.5.9 gorm.io/gorm v1.25.12 @@ -13,10 +14,6 @@ require ( require ( cloud.google.com/go/compute/metadata v0.3.0 // indirect github.com/andybalholm/brotli v1.1.1 // indirect - github.com/fasthttp/websocket v1.5.10 // indirect - github.com/gofiber/contrib/websocket v1.3.2 // indirect - github.com/gofiber/jwt/v3 v3.3.10 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -29,12 +26,9 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.57.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect - golang.org/x/crypto v0.29.0 // indirect - golang.org/x/net v0.31.0 // indirect golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect diff --git a/backend/go.sum b/backend/go.sum index cdb8643..5125c40 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,25 +1,16 @@ cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fasthttp/websocket v1.5.10 h1:bc7NIGyrg1L6sd5pRzCIbXpro54SZLEluZCu0rOpcN4= -github.com/fasthttp/websocket v1.5.10/go.mod h1:BwHeuXGWzCW1/BIKUKD3+qfCl+cTdsHu/f243NcAI/Q= -github.com/gofiber/contrib/websocket v1.3.2 h1:AUq5PYeKwK50s0nQrnluuINYeep1c4nRCJ0NWsV3cvg= -github.com/gofiber/contrib/websocket v1.3.2/go.mod h1:07u6QGMsvX+sx7iGNCl5xhzuUVArWwLQ3tBIH24i+S8= -github.com/gofiber/fiber/v2 v2.45.0/go.mod h1:DNl0/c37WLe0g92U6lx1VMQuxGUQY5V7EIaVoEsUffc= github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo= github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= -github.com/gofiber/jwt/v3 v3.3.10 h1:0bpWtFKaGepjwYTU4efHfy0o+matSqZwTxGMo5a+uuc= -github.com/gofiber/jwt/v3 v3.3.10/go.mod h1:GJorFVaDyfMPSK9RB8RG4NQ3s1oXKTmYaoL/ny08O1A= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -34,123 +25,45 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8= -github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= -github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= -github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 h1:D0vL7YNisV2yqE55+q0lFuGse6U8lxlg7fYTctlT5Gc= -github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= -github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fasthttp v1.57.0 h1:Xw8SjWGEP/+wAAgyy5XTvgrWlOD1+TxbbvNADYCm1Tg= github.com/valyala/fasthttp v1.57.0/go.mod h1:h6ZBaPRlzpZ6O3H5t2gEk1Qi33+TmLvfwgLLp0t9CpE= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/backend/handlers/budget_handler.go b/backend/handlers/budget_handler.go index 8c1dc74..06fe4ad 100644 --- a/backend/handlers/budget_handler.go +++ b/backend/handlers/budget_handler.go @@ -2,8 +2,8 @@ package handlers import ( "github.com/gofiber/fiber/v2" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/models" + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/models" ) func CreateBudget(c *fiber.Ctx) error { diff --git a/backend/handlers/category_handler.go b/backend/handlers/category_handler.go index d395c6f..88e5029 100644 --- a/backend/handlers/category_handler.go +++ b/backend/handlers/category_handler.go @@ -5,8 +5,8 @@ import ( "strconv" "github.com/gofiber/fiber/v2" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/models" + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/models" ) func CreateCategory(c *fiber.Ctx) error { diff --git a/backend/handlers/plan_handler.go b/backend/handlers/plan_handler.go index c7f8505..895c3e2 100644 --- a/backend/handlers/plan_handler.go +++ b/backend/handlers/plan_handler.go @@ -11,7 +11,7 @@ import ( // "github.com/golang-jwt/jwt/v4" // "golang.org/x/crypto/bcrypt" - "github.com/long104/CashWise/models" + "github.com/long104/SenZen/models" "gorm.io/gorm" ) @@ -22,8 +22,8 @@ func GetPlanByID(db *gorm.DB, c *fiber.Ctx) error { var plan models.Plan if err := db.Preload("Transactions.Category").First(&plan, planId).Error; err != nil { - // if err := db.Preload(clause.Associations).First(&plan, planId).Error; err != nil { - // if err := db.First(&plan, planId).Error; err != nil { + // if err := db.Preload(clause.Associations).First(&plan, planId).Error; err != nil { + // if err := db.First(&plan, planId).Error; err != nil { log.Println("Error fetching plan:", err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot fetch plan"}) } diff --git a/backend/handlers/transaction_handler.go b/backend/handlers/transaction_handler.go index 9ac5d80..2e38ea9 100644 --- a/backend/handlers/transaction_handler.go +++ b/backend/handlers/transaction_handler.go @@ -8,8 +8,8 @@ import ( "strconv" "github.com/gofiber/fiber/v2" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/models" + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/models" ) // gorm.Model diff --git a/backend/handlers/user_handler.go b/backend/handlers/user_handler.go index b8cef7c..2b4be38 100644 --- a/backend/handlers/user_handler.go +++ b/backend/handlers/user_handler.go @@ -4,28 +4,27 @@ import ( "log" "github.com/gofiber/fiber/v2" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/models" + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/models" ) // loginUser handles user in -func GetUsers(c *fiber.Ctx) error { - var users []models.User +func GetUsers(c *fiber.Ctx) error { var users []models.User config.DB.Find(&users) return c.JSON(users) } func GetUser(c *fiber.Ctx) error { - id := c.Params("id") - var user models.User + id := c.Params("id") + var user models.User - if err := config.DB.First(&user, id).Error; err != nil { - log.Println("Error fetching user:", err) - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot fetch user"}) - } + if err := config.DB.First(&user, id).Error; err != nil { + log.Println("Error fetching user:", err) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Cannot fetch user"}) + } - return c.JSON(user) + return c.JSON(user) } // createBook creates a new book diff --git a/backend/main.go b/backend/main.go deleted file mode 100644 index 6531b2c..0000000 --- a/backend/main.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "log" - // "os" - - "github.com/gofiber/contrib/websocket" - "github.com/gofiber/fiber/v2" - // jwtware "github.com/gofiber/jwt/v3" - "github.com/joho/godotenv" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/middleware" - "github.com/long104/CashWise/routes" -) - -func main() { - err := godotenv.Load(".env") - if err != nil { - log.Fatalf("Some error occurred. Err: %s", err) - } - config.ConnectDatabase() - app := fiber.New() - - - app.Use(middleware.CORSMiddleware()) - - - app.Get("api/health", func(c *fiber.Ctx) error { - return c.SendString("health check ok") - }) - - app.Use("api/ws", func(c *fiber.Ctx) error { - // IsWebSocketUpgrade returns true if the client - // requested upgrade to the WebSocket protocol. - if websocket.IsWebSocketUpgrade(c) { - c.Locals("allowed", true) - return c.Next() - } - return fiber.ErrUpgradeRequired - }) - - routes.WsRoutes(app) - routes.SetupOAuthRoutes(app) - routes.SetupAuthRoutes(app) - - // app.Use(jwtware.New(jwtware.Config{ - // SigningKey: []byte(os.Getenv("jwtSecretKey")), - // })) - - // app.Use("/admin", middleware.checkMiddleware) - // app.Use("/books", AuthRequired) - app.Get("api/validate-token", middleware.ValidateToken) - - routes.SetupRoutes(app) - - // setupRoutes(app) - - app.Listen(":8080") -} diff --git a/backend/middleware/cors_middleware.go b/backend/middleware/cors_middleware.go index eb5c02d..3ad65d6 100644 --- a/backend/middleware/cors_middleware.go +++ b/backend/middleware/cors_middleware.go @@ -13,11 +13,12 @@ func CORSMiddleware() fiber.Handler { // frontendOrigin = "http://localhost:3000" // Default for development // } return cors.New(cors.Config{ - AllowMethods: "GET,POST,HEAD,PUT,DELETE,PATCH", - AllowHeaders: "Origin, Content-Type, Accept, Authorization", - // AllowOrigins: "http://localhost:3000", // Set to your frontend origin - // AllowOrigins: frontendOrigin, - AllowOrigins: "http://cashwise.com", // Set to your frontend origin - AllowCredentials: true, // Allows cookies and credentials to be sent + AllowMethods: "GET,POST,HEAD,PUT,DELETE,PATCH", + AllowHeaders: "Origin, Content-Type, Accept, Authorization", + // AllowOrigins: "http://localhost:3000", // Set to your frontend origin + AllowOrigins: "https://senzen-frontend.vercel.app", + // AllowOrigins: frontendOrigin, + // AllowOrigins: "http://cashwise.com", // Set to your frontend origin + AllowCredentials: true, // Allows cookies and credentials to be sent }) } diff --git a/backend/models/plan.go b/backend/models/plan.go index d300473..6d05f09 100644 --- a/backend/models/plan.go +++ b/backend/models/plan.go @@ -3,26 +3,25 @@ package models import ( "time" - // "gorm.io/gorm" ) // Plan represents a user's financial plan. type Plan struct { - ID int64 `gorm:"primaryKey" json:"id"` - UserID int64 `gorm:"not null" json:"user_id"` - Name string `gorm:"not null" json:"name"` - PlanType string `gorm:"not null" json:"plan_type"` - Visibility string `gorm:"not null" json:"visibility"` - Duration string `gorm:"not null" json:"duration"` - Description string `json:"description,omitempty"` - AutoSave bool `gorm:"not null" json:"auto_save"` - InitialBudget float64 `gorm:"not null" json:"initial_budget"` - CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` - User User `gorm:"foreignKey:UserID" json:"-"` - Budgets []Budget `gorm:"foreignKey:PlanID;onDelete:CASCADE"` - Transactions []Transaction `gorm:"foreignKey:PlanID;onDelete:CASCADE"` - Categories []Category `gorm:"foreignKey:PlanID;onDelete:CASCADE"` + ID int64 `gorm:"primaryKey" json:"id"` + UserID int64 `gorm:"not null" json:"user_id"` + Name string `gorm:"not null" json:"name"` + PlanType string `gorm:"not null" json:"plan_type"` + Visibility string `gorm:"not null" json:"visibility"` + Duration string `gorm:"not null" json:"duration"` + Description string `json:"description,omitempty"` + AutoSave bool `gorm:"not null" json:"auto_save"` + InitialBudget float64 `gorm:"not null" json:"initial_budget"` + CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` + User User `gorm:"foreignKey:UserID" json:"-"` + Budgets []Budget `gorm:"foreignKey:PlanID;onDelete:CASCADE"` + Transactions []Transaction `gorm:"foreignKey:PlanID;onDelete:CASCADE"` + Categories []Category `gorm:"foreignKey:PlanID;onDelete:CASCADE"` // Deleted gorm.DeletedAt `gorm:"index" json:"-"` } diff --git a/backend/routes/auth_routes.go b/backend/routes/auth_routes.go index 5426346..baafc0f 100644 --- a/backend/routes/auth_routes.go +++ b/backend/routes/auth_routes.go @@ -2,7 +2,7 @@ package routes import ( "github.com/gofiber/fiber/v2" - "github.com/long104/CashWise/controllers" + "github.com/long104/SenZen/controllers" ) func SetupAuthRoutes(app *fiber.App) { diff --git a/backend/routes/oauth_routes.go b/backend/routes/oauth_routes.go index e730b91..8338b2e 100644 --- a/backend/routes/oauth_routes.go +++ b/backend/routes/oauth_routes.go @@ -3,8 +3,8 @@ package routes import ( "github.com/gofiber/fiber/v2" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/controllers" // Adjust import path as needed + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/controllers" // Adjust import path as needed ) func SetupOAuthRoutes(app *fiber.App) { diff --git a/backend/routes/routes.go b/backend/routes/routes.go index 4e861bb..6b54dd3 100644 --- a/backend/routes/routes.go +++ b/backend/routes/routes.go @@ -2,8 +2,8 @@ package routes import ( "github.com/gofiber/fiber/v2" - "github.com/long104/CashWise/config" - "github.com/long104/CashWise/handlers" + "github.com/long104/SenZen/config" + "github.com/long104/SenZen/handlers" ) func SetupRoutes(app *fiber.App) { @@ -15,7 +15,7 @@ func SetupRoutes(app *fiber.App) { // transaction app.Post("api/transaction", handlers.CreateTransaction) app.Delete("api/transaction", handlers.DeleteTransaction) - app.Get("api/transaction/:planId", handlers.GetPlanTransactions) + app.Get("api/transaction/:planId", handlers.GetPlanTransactions) // app.Delete("/transaction/:id", handlers.DeleteTransaction) // app.Post("/transaction/:id", handlers.CreateTransaction) @@ -29,7 +29,7 @@ func SetupRoutes(app *fiber.App) { app.Get("api/plan/:id", func(c *fiber.Ctx) error { return handlers.GetPlanByID(config.DB, c) }) - app.Get("api/plans/:id", func(c *fiber.Ctx) error { + app.Get("api/plans/:id", func(c *fiber.Ctx) error { return handlers.GetPlans(config.DB, c) }) app.Post("api/plan", func(c *fiber.Ctx) error { diff --git a/backend/routes/ws.go b/backend/routes/ws.go deleted file mode 100644 index ffec9ec..0000000 --- a/backend/routes/ws.go +++ /dev/null @@ -1,76 +0,0 @@ -package routes - -import ( - "log" - "sync" - - "github.com/gofiber/contrib/websocket" - "github.com/gofiber/fiber/v2" - // "github.com/long104/CashWise/middleware" -) - -type WebSocketHub struct { - clients map[*websocket.Conn]bool - broadcast chan []byte - lock sync.Mutex -} - -var hub = WebSocketHub{ - clients: make(map[*websocket.Conn]bool), - broadcast: make(chan []byte), -} - -func WsRoutes(app *fiber.App) { - app.Get("api/ws/:id", websocket.New(func(c *websocket.Conn) { - // token := c.Query("token") - // if result := middleware.IsValidToken(token); !result { - // log.Println("inValid token") - // } - - log.Println(c.Locals("allowed")) // true - log.Println(c.Params("id")) // 123 - log.Println(c.Query("v")) // 1.0 - log.Println(c.Cookies("session")) // "" - - hub.lock.Lock() - hub.clients[c] = true - hub.lock.Unlock() - - log.Println("New client connected") - defer func() { - hub.lock.Lock() - delete(hub.clients, c) - hub.lock.Unlock() - log.Println("Client disconnected") - c.Close() - }() - - for { - _, msg, err := c.ReadMessage() - if err != nil { - log.Println("read error:", err) - break - } - log.Printf("Received: %s", msg) - - // Broadcast the message to all clients - hub.broadcast <- msg - } - })) - - // Start a separate goroutine to handle broadcasting - go func() { - for { - msg := <-hub.broadcast - hub.lock.Lock() - for client := range hub.clients { - if err := client.WriteMessage(websocket.TextMessage, msg); err != nil { - log.Println("write error:", err) - client.Close() - delete(hub.clients, client) - } - } - hub.lock.Unlock() - } - }() -} diff --git a/backend/vercel.json b/backend/vercel.json new file mode 100644 index 0000000..5be778e --- /dev/null +++ b/backend/vercel.json @@ -0,0 +1,5 @@ +{ + "rewrites": [ + { "source": "(.*)", "destination": "api/index.go" } + ] +} From cb73e16d5293661387500f74fcbd55810f5588a8 Mon Sep 17 00:00:00 2001 From: pantorn Date: Fri, 4 Apr 2025 03:14:45 +0700 Subject: [PATCH 02/11] fix oauth --- frontend/.env.local | 8 ++ frontend/.env.production | 8 +- frontend/.gitignore | 1 + .../src/app/(landingPage)/sign-in/page.tsx | 127 +++++++++--------- .../src/app/(landingPage)/sign-up/page.tsx | 5 +- 5 files changed, 80 insertions(+), 69 deletions(-) create mode 100644 frontend/.env.local create mode 100644 frontend/.gitignore diff --git a/frontend/.env.local b/frontend/.env.local new file mode 100644 index 0000000..7ba8ead --- /dev/null +++ b/frontend/.env.local @@ -0,0 +1,8 @@ +# NEXT_PUBLIC_BASE_URL=http://localhost:3000 +# NEXT_PUBLIC_BACKEND=http://localhost:8080 +# NEXT_PUBLIC_BACKEND=http://cashwise.com/api +# NEXT_PUBLIC_BACKEND=http://cashwise.localhost +# NEXT_PUBLIC_BACKEND=http://localhost:8080/api + +NEXT_PUBLIC_BASE_URL=https://senzen-frontend.vercel.app +NEXT_PUBLIC_BACKEND=https://senzen-backend.vercel.app diff --git a/frontend/.env.production b/frontend/.env.production index 079ee02..1c11262 100644 --- a/frontend/.env.production +++ b/frontend/.env.production @@ -1,6 +1,2 @@ -NEXT_PUBLIC_BASE_URL=http://localhost:3000 -# NEXT_PUBLIC_BACKEND=http://localhost:8080 -NEXT_PUBLIC_BACKEND=http://cashwise.com/api -# NEXT_PUBLIC_BACKEND=http://cashwise.localhost -# NEXT_PUBLIC_BACKEND=http://localhost:8080/api -# NEXT_PUBLIC_BACKEND=http://localhost:8080/api +NEXT_PUBLIC_BASE_URL=https://senzen-frontend.vercel.app +NEXT_PUBLIC_BACKEND=https://senzen-backend.vercel.app/api diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..e985853 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1 @@ +.vercel diff --git a/frontend/src/app/(landingPage)/sign-in/page.tsx b/frontend/src/app/(landingPage)/sign-in/page.tsx index 6bfd4aa..bab0a87 100644 --- a/frontend/src/app/(landingPage)/sign-in/page.tsx +++ b/frontend/src/app/(landingPage)/sign-in/page.tsx @@ -34,6 +34,7 @@ export default function LoginPage() { setIsSubmitting(true); try { + console.log(process.env.NEXT_PUBLIC_BACKEND + "/login"); const response = await fetch(process.env.NEXT_PUBLIC_BACKEND + "/login", { method: "POST", headers: { @@ -86,71 +87,73 @@ export default function LoginPage() {
- {/* */} - - {/* */} - - {/* */} - + + - - Login with GitHub - - {/* */} + +
diff --git a/frontend/src/app/(landingPage)/sign-up/page.tsx b/frontend/src/app/(landingPage)/sign-up/page.tsx index 0202ee5..05bcae4 100644 --- a/frontend/src/app/(landingPage)/sign-up/page.tsx +++ b/frontend/src/app/(landingPage)/sign-up/page.tsx @@ -9,7 +9,8 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import Link from "next/link"; import { useRouter } from "next/navigation"; @@ -43,6 +44,8 @@ export default function Component() { // console.log(email,password,name) try { + console.log(process.env.NEXT_PUBLIC_BACKEND + "/signup"); + const response = await fetch( process.env.NEXT_PUBLIC_BACKEND + "/signup", { From 7c6191003e0af3f748c25f533bda39ce2d26a2c3 Mon Sep 17 00:00:00 2001 From: pantorn Date: Fri, 4 Apr 2025 15:16:07 +0700 Subject: [PATCH 03/11] try to do in local --- backend/controllers/google.go | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/backend/controllers/google.go b/backend/controllers/google.go index 85088a5..8ba8517 100644 --- a/backend/controllers/google.go +++ b/backend/controllers/google.go @@ -99,30 +99,27 @@ func GoogleCallback(c *fiber.Ctx) error { } // Create a new user - result := db.Create(&models.User{Name: userName, Email: userEmail}) - if result.Error != nil { - return c.JSON(map[string]any{ - "Status": http.StatusInternalServerError, - "Error": result.Error, - }) - } - - - - + result := db.Create(&models.User{Name: userName, Email: userEmail}) + if result.Error != nil { + return c.JSON(map[string]any{ + "Status": http.StatusInternalServerError, + "Error": result.Error, + }) + } var userDatabase models.User res := db.Where("email = ?", userEmail).First(&userDatabase) if res.RowsAffected == 0 { - result := db.Create(&models.User{Name: userName, Email: userEmail}) - if result.Error != nil { - return c.JSON(map[string]any{ - "Status": http.StatusInternalServerError, - "Error": result.Error, - }) - } } + result := db.Create(&models.User{Name: userName, Email: userEmail}) + if result.Error != nil { + return c.JSON(map[string]any{ + "Status": http.StatusInternalServerError, + "Error": result.Error, + }) + } + } appToken := jwt.New(jwt.SigningMethodHS256) claims := appToken.Claims.(jwt.MapClaims) @@ -132,29 +129,32 @@ func GoogleCallback(c *fiber.Ctx) error { claims["role"] = "admin" claims["name"] = userName claims["email"] = userEmail -// claims["role"] = "memeber" + // claims["role"] = "memeber" t, err := appToken.SignedString([]byte(os.Getenv("jwtSecretKey"))) if err != nil { return c.SendStatus(fiber.StatusInternalServerError) } - // Set cookie c.Cookie(&fiber.Cookie{ Name: "jwt", Value: t, - // Path: "/", + Path: "/", Expires: time.Now().Add(time.Hour * 72), // HTTPOnly: true, - // Domain: "https://senzen-frontend.vercel.app", - Secure: false, - SameSite: "Lax", + // Secure: false, + // Domain: "https://senzen-frontend.vercel.app", + HTTPOnly: true, + Secure: true, + SameSite: "None", + // SameSite: "Lax", }) // return c.SendString(string(userData)) // return c.Redirect("http://localhost:3000/home") - fmt.Print("ip is ",c.IP()) + fmt.Print("ip is dddddddddddddddddddddddddddddd", c.IP()) + log.Print("ip is dddddddddddddddddddddddddddddd", c.IP()) return c.Redirect(os.Getenv("FRONTEND_URL") + "/home") } From 33bfd21a63591e85d191234f59e444ac763c2188 Mon Sep 17 00:00:00 2001 From: pantorn Date: Thu, 8 May 2025 10:06:37 +0700 Subject: [PATCH 04/11] remove Unnecessary --- frontend/.env.production | 1 + frontend/src/app/(landingPage)/page.tsx | 4 +- .../src/app/(landingPage)/sign-in/page.tsx | 5 +- .../src/app/(landingPage)/sign-up/page.tsx | 1 - frontend/src/app/(product)/home/page.tsx | 18 ++- frontend/src/components/app-sidebar.tsx | 119 +++++++++--------- frontend/src/components/nav-projects.tsx | 13 +- frontend/src/components/nav-user.tsx | 60 +++++---- frontend/src/middleware.ts | 7 +- 9 files changed, 131 insertions(+), 97 deletions(-) diff --git a/frontend/.env.production b/frontend/.env.production index 1c11262..9e8f3cc 100644 --- a/frontend/.env.production +++ b/frontend/.env.production @@ -1,2 +1,3 @@ + NEXT_PUBLIC_BASE_URL=https://senzen-frontend.vercel.app NEXT_PUBLIC_BACKEND=https://senzen-backend.vercel.app/api diff --git a/frontend/src/app/(landingPage)/page.tsx b/frontend/src/app/(landingPage)/page.tsx index b2c6386..70b1d8e 100644 --- a/frontend/src/app/(landingPage)/page.tsx +++ b/frontend/src/app/(landingPage)/page.tsx @@ -10,8 +10,8 @@ export default function Home() { {/*
*/} - - + {/* */} + {/* */}
{/*
*/} diff --git a/frontend/src/app/(landingPage)/sign-in/page.tsx b/frontend/src/app/(landingPage)/sign-in/page.tsx index bab0a87..fc55038 100644 --- a/frontend/src/app/(landingPage)/sign-in/page.tsx +++ b/frontend/src/app/(landingPage)/sign-in/page.tsx @@ -13,9 +13,10 @@ import { Label } from "@/components/ui/label"; import { Separator } from "@/components/ui/separator"; import Link from "next/link"; import { Github } from "lucide-react"; -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import Cookies from "js-cookie"; +import { jwtDecode } from "jwt-decode"; import useAuthStore from "@/zustand/auth"; @@ -58,6 +59,7 @@ export default function LoginPage() { return; } logins(String(token)); + console.log("login"); // (event.currentTarget as HTMLFormElement)?.reset(); router.push("/home"); // router.refresh(); @@ -73,6 +75,7 @@ export default function LoginPage() { }; // const google_login = process.env.NEXT_PUBLIC_BACKEND + `/google_login`; // const github_login = process.env.NEXT_PUBLIC_BACKEND + `/github_login`; + // Inside the redirected-to page/component return (
diff --git a/frontend/src/app/(landingPage)/sign-up/page.tsx b/frontend/src/app/(landingPage)/sign-up/page.tsx index 05bcae4..eca8ba5 100644 --- a/frontend/src/app/(landingPage)/sign-up/page.tsx +++ b/frontend/src/app/(landingPage)/sign-up/page.tsx @@ -14,7 +14,6 @@ import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import Link from "next/link"; import { useRouter } from "next/navigation"; - export default function Component() { const router = useRouter(); const [passwordMatch, setPasswordMatch] = useState(true); diff --git a/frontend/src/app/(product)/home/page.tsx b/frontend/src/app/(product)/home/page.tsx index bad2b3c..2b0bb27 100644 --- a/frontend/src/app/(product)/home/page.tsx +++ b/frontend/src/app/(product)/home/page.tsx @@ -1,6 +1,6 @@ "use client"; -import React from "react"; +import React, { useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Card, @@ -15,11 +15,13 @@ import { useRouter } from "next/navigation"; import { usePlan } from "@/hooks/usePlan"; import { z } from "zod"; import { PlanSchema } from "@/types"; +import useAuthStore from "@/zustand/auth"; export default function FinancialPlans() { type Plan = z.infer; const { plansQuery, deletePlanMutation } = usePlan(); const { data: plans } = plansQuery; + const logins = useAuthStore((state) => state.login); const router = useRouter(); async function goToPlan(planName: string, planId: number) { @@ -39,6 +41,20 @@ export default function FinancialPlans() { } } + useEffect(() => { + const token = document.cookie?.split("jwt=")[1]; + // .find((row) => row.startsWith("jwt=")) + // ?.split("=")[1]; + + console.log("login work", token); + if (token) { + // localStorage.setItem("token", token); + // logins(String(token)); + logins(String(token)); + } + }, []); + + console.log(); return (
diff --git a/frontend/src/components/app-sidebar.tsx b/frontend/src/components/app-sidebar.tsx index b337763..ef8efd8 100644 --- a/frontend/src/components/app-sidebar.tsx +++ b/frontend/src/components/app-sidebar.tsx @@ -15,7 +15,8 @@ import { NavMain } from "@/components/nav-main"; import { NavProjects } from "@/components/nav-projects"; import { NavUser } from "@/components/nav-user"; import { TeamSwitcher } from "@/components/team-switcher"; -import { Sidebar, +import { + Sidebar, SidebarContent, SidebarFooter, SidebarHeader, @@ -42,16 +43,16 @@ export function AppSidebar({ ...props }: React.ComponentProps) { logo: Building2, plan: "Company", }, - { - name: "Pricing", - logo: Package, - plan: "pricing", - }, - { - name: "About Us", - logo: GalleryVerticalEnd, - plan: "About us", - }, + // { + // name: "Pricing", + // logo: Package, + // plan: "pricing", + // }, + // { + // name: "About Us", + // logo: GalleryVerticalEnd, + // plan: "About us", + // }, ], navMain: [ { @@ -59,54 +60,54 @@ export function AppSidebar({ ...props }: React.ComponentProps) { url: "#", icon: NotebookPen, // isActive: true, - items: + items: plans?.map((plan: any) => ({ title: plan?.name || "Unnamed Plan", url: `/plan/${plan?.name}/?id=${plan.id}`, })) || [], }, - { - title: "News&Forums", - url: "#", - icon: Newspaper, - items: [ - { - title: "Money", - url: "#", - }, - { - title: "Saving", - url: "#", - }, - { - title: "Story", - url: "#", - }, - ], - }, - { - title: "Settings", - url: "#", - icon: Settings2, - items: [ - { - title: "General", - url: "#", - }, - { - title: "Team", - url: "#", - }, - { - title: "Billing", - url: "#", - }, - { - title: "Limits", - url: "#", - }, - ], - }, + // { + // title: "News&Forums", + // url: "#", + // icon: Newspaper, + // items: [ + // { + // title: "Money", + // url: "#", + // }, + // { + // title: "Saving", + // url: "#", + // }, + // { + // title: "Story", + // url: "#", + // }, + // ], + // }, + // { + // title: "Settings", + // url: "#", + // icon: Settings2, + // items: [ + // { + // title: "General", + // url: "#", + // }, + // { + // title: "Team", + // url: "#", + // }, + // { + // title: "Billing", + // url: "#", + // }, + // { + // title: "Limits", + // url: "#", + // }, + // ], + // }, ], projects: [ { @@ -119,11 +120,11 @@ export function AppSidebar({ ...props }: React.ComponentProps) { url: "#plan", icon: Newspaper, }, - { - name: "News", - url: "#news", - icon: Newspaper, - }, + // { + // name: "News", + // url: "#news", + // icon: Newspaper, + // }, ], }; // useEffect(() => {}, []); diff --git a/frontend/src/components/nav-projects.tsx b/frontend/src/components/nav-projects.tsx index 71ca160..2ac3d9b 100644 --- a/frontend/src/components/nav-projects.tsx +++ b/frontend/src/components/nav-projects.tsx @@ -78,12 +78,13 @@ export function NavProjects({ ))} - - - - More - - + {/* ... more icon */} + {/* */} + {/* */} + {/* */} + {/* More */} + {/* */} + {/* */} ); diff --git a/frontend/src/components/nav-user.tsx b/frontend/src/components/nav-user.tsx index 8fa5a6a..dd1b5cf 100644 --- a/frontend/src/components/nav-user.tsx +++ b/frontend/src/components/nav-user.tsx @@ -43,8 +43,16 @@ export function NavUser({ const router = useRouter(); - const handleLogout = () => { - logout(); // Clear user state and cookies + const handleLogout = async () => { + // logout(); // Clear user state and cookies + const response = await fetch(process.env.NEXT_PUBLIC_BACKEND + "/logout", { + method: "POST", + credentials: "include", // Include cookies in the request + }); + const data = await response.json(); + console.log(data.message); + document.cookie = "jwt=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; + localStorage.clear(); router.push("/sign-in"); // Redirect to sign-in page }; @@ -86,32 +94,32 @@ export function NavUser({
- - - - - Upgrade to Pro - - - - - - - Account - - - - Billing - - - - Notifications - - + {/* */} + {/* */} + {/* */} + {/* */} + {/* Upgrade to Pro */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* Account */} + {/* */} + {/* */} + {/* */} + {/* Billing */} + {/* */} + {/* */} + {/* */} + {/* Notifications */} + {/* */} + {/* */} - - Log out + + Log out diff --git a/frontend/src/middleware.ts b/frontend/src/middleware.ts index e572e70..84aaa64 100644 --- a/frontend/src/middleware.ts +++ b/frontend/src/middleware.ts @@ -1,9 +1,12 @@ +// 'use client' import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { jwtDecode } from "jwt-decode"; +// import useAuthStore from "@/zustand/auth"; export async function middleware(req: NextRequest) { const token = req.cookies.get("jwt"); + // const login = useAuthStore((state) => state.login) const handleLogout = async () => { try { @@ -34,12 +37,14 @@ export async function middleware(req: NextRequest) { const redirectToHome = ["", "/sign-in", "/sign-up"]; // Adjust for root path "" + const decoded = jwtDecode<{ exp: number }>(token.value); // Decode the token + if (redirectToHome.includes(path) && token) { // return NextResponse.redirect("http://localhost:3000/home"); + // login(String(token)) return NextResponse.redirect(new URL("/home", req.url)); } - const decoded = jwtDecode<{ exp: number }>(token.value); // Decode the token const exp = decoded.exp * 1000; // Convert to milliseconds const currentTime = Date.now(); From 371743f126e46b83bfa264ebdcbccfde20cf8b0c Mon Sep 17 00:00:00 2001 From: pantorn Date: Thu, 8 May 2025 10:49:47 +0700 Subject: [PATCH 05/11] fix oauth --- backend/config/config.go | 7 ++- backend/controllers/auth_controller.go | 22 +++++-- backend/controllers/github.go | 30 +++++++--- backend/controllers/google.go | 79 ++++++++++++++++++-------- backend/middleware/cors_middleware.go | 7 ++- 5 files changed, 102 insertions(+), 43 deletions(-) diff --git a/backend/config/config.go b/backend/config/config.go index a150f5b..5e3ae5e 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -15,11 +15,11 @@ type Config struct { } var AppConfig Config - func GoogleConfig() oauth2.Config { AppConfig.GoogleLoginConfig = oauth2.Config{ // RedirectURL: "http://localhost:8080/google_callback", - RedirectURL: "https://senzen-backend.vercel.app/google_callback", + // RedirectURL: "https://senzen-backend.vercel.app/google_callback", + RedirectURL: "https://backend.pantorn.me/google_callback", ClientID: os.Getenv("GOOGLE_CLIENT_ID"), ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), Scopes: []string{ @@ -35,7 +35,8 @@ func GoogleConfig() oauth2.Config { func GithubConfig() oauth2.Config { AppConfig.GitHubLoginConfig = oauth2.Config{ // RedirectURL: "http://localhost:8080/github_callback", - RedirectURL: "https://senzen-backend.vercel.app/google_callback", + // RedirectURL: "https://senzen-backend.vercel.app/google_callback", + RedirectURL: "https://backend.pantorn.me/github_callback", ClientID: os.Getenv("GITHUB_CLIENT_ID"), // RedirectURL: fmt.Sprintf( // "https://github.com/login/oauth/authorize?scope=user:repo&client_id=%s&redirect_uri=%s", os.Getenv("GITHUB_CLIENT_ID"), "http://localhost:8080/github_callback"), diff --git a/backend/controllers/auth_controller.go b/backend/controllers/auth_controller.go index b9748c8..95de15f 100644 --- a/backend/controllers/auth_controller.go +++ b/backend/controllers/auth_controller.go @@ -12,6 +12,7 @@ import ( "golang.org/x/crypto/bcrypt" ) + func CreateUser(c *fiber.Ctx) error { user := new(models.User) if err := c.BodyParser(user); err != nil { @@ -74,7 +75,7 @@ func LoginUser(c *fiber.Ctx) error { Name: "jwt", Value: t, Path: "/", - // Domain: "cashwise.com", + Domain: ".pantorn.me", Expires: time.Now().Add(time.Hour * 72), // HTTPOnly: true, // Secure: false, @@ -86,8 +87,21 @@ func LoginUser(c *fiber.Ctx) error { return c.JSON(fiber.Map{"token": t, "message": "success"}) } +// func LogoutUser(c *fiber.Ctx) error { +// // Clear the JWT cookie +// c.ClearCookie("jwt") +// return c.JSON(fiber.Map{"message": "Successfully logged out"}) +// } + func LogoutUser(c *fiber.Ctx) error { - // Clear the JWT cookie - c.ClearCookie("jwt") - return c.JSON(fiber.Map{"message": "Successfully logged out"}) + c.Cookie(&fiber.Cookie{ + Name: "jwt", + Value: "", + Path: "/", // Ensure this matches the original path + Domain: ".pantorn.me", // Ensure this matches the original domain + Expires: time.Now().Add(-1 * time.Hour), // Set expiration in the past + HTTPOnly: true, + Secure: true, + }) + return c.JSON(fiber.Map{"message": "Successfully logged out"}) } diff --git a/backend/controllers/github.go b/backend/controllers/github.go index 1159d5d..d38169c 100644 --- a/backend/controllers/github.go +++ b/backend/controllers/github.go @@ -1,4 +1,5 @@ package controllers + import ( "context" "encoding/json" @@ -123,20 +124,31 @@ func GithubCallback(c *fiber.Ctx) error { // Set cookie c.Cookie(&fiber.Cookie{ - Name: "jwt", - Value: t, - Path: "/", - // Domain: "cashwise.com", - Domain: "https://senzen-frontend.vercel.app", - Expires: time.Now().Add(time.Hour * 72), - // Secure: false, - // HTTPOnly: true, + // Name: "jwt", + // Value: t, + // Path: "/", + // // Domain: "cashwise.com", + // Domain: "https://senzen-frontend.vercel.app", + // Expires: time.Now().Add(time.Hour * 72), + // // Secure: false, + // // HTTPOnly: true, + // HTTPOnly: false, + // SameSite: "Lax", + + Name: "jwt", + Value: t, + Path: "/", + Expires: time.Now().Add(time.Hour * 72), HTTPOnly: false, SameSite: "Lax", + // HTTPOnly: true, + // Secure: true, // required for cross-site cookies over HTTPS + // SameSite: "None", // allow sending cookies cross-site + Domain: ".pantorn.me", }) // return c.SendString(string(userData)) // return c.Redirect("http://localhost:3000/") // return c.Redirect("http://localhost:3000/home") - return c.Redirect(os.Getenv("FRONEND_URL") + "/home") + return c.Redirect(os.Getenv("FRONTEND_URL") + "/home") } diff --git a/backend/controllers/google.go b/backend/controllers/google.go index 8ba8517..905841f 100644 --- a/backend/controllers/google.go +++ b/backend/controllers/google.go @@ -99,26 +99,28 @@ func GoogleCallback(c *fiber.Ctx) error { } // Create a new user - result := db.Create(&models.User{Name: userName, Email: userEmail}) - if result.Error != nil { - return c.JSON(map[string]any{ - "Status": http.StatusInternalServerError, - "Error": result.Error, - }) - } + db.Create(&models.User{Name: userName, Email: userEmail}) + // result := db.Create(&models.User{Name: userName, Email: userEmail}) + // if result.Error != nil { + // return c.JSON(map[string]any{ + // "Status": http.StatusInternalServerError, + // "Error": result.Error, + // }) + // } var userDatabase models.User res := db.Where("email = ?", userEmail).First(&userDatabase) if res.RowsAffected == 0 { - result := db.Create(&models.User{Name: userName, Email: userEmail}) - if result.Error != nil { - return c.JSON(map[string]any{ - "Status": http.StatusInternalServerError, - "Error": result.Error, - }) - } + // result := db.Create(&models.User{Name: userName, Email: userEmail}) + db.Create(&models.User{Name: userName, Email: userEmail}) + // if result.Error != nil { + // return c.JSON(map[string]any{ + // "Status": http.StatusInternalServerError, + // "Error": result.Error, + // }) + // } } appToken := jwt.New(jwt.SigningMethodHS256) @@ -138,23 +140,50 @@ func GoogleCallback(c *fiber.Ctx) error { // Set cookie c.Cookie(&fiber.Cookie{ - Name: "jwt", - Value: t, - Path: "/", - Expires: time.Now().Add(time.Hour * 72), - // HTTPOnly: true, - // Secure: false, - // Domain: "https://senzen-frontend.vercel.app", - HTTPOnly: true, - Secure: true, - SameSite: "None", + // Name: "jwt", + // Value: t, + // Path: "/", + // Expires: time.Now().Add(time.Hour * 72), + // HTTPOnly: false, // SameSite: "Lax", + + Name: "jwt", + Value: t, + Path: "/", + Expires: time.Now().Add(time.Hour * 72), + HTTPOnly: false, + SameSite: "Lax", + // HTTPOnly: true, + // Secure: true, // required for cross-site cookies over HTTPS + // SameSite: "None", // allow sending cookies cross-site + Domain: ".pantorn.me", }) // return c.SendString(string(userData)) // return c.Redirect("http://localhost:3000/home") fmt.Print("ip is dddddddddddddddddddddddddddddd", c.IP()) - log.Print("ip is dddddddddddddddddddddddddddddd", c.IP()) + // log.Print("ip is dddddddddddddddddddddddddddddd", c.IP()) + // return c.JSON(fiber.Map{ + // "message": "Cookie set", + // "token": t, + // }) + return c.Redirect(os.Getenv("FRONTEND_URL") + "/home") + // return c.Redirect(os.Getenv("FRONTEND_URL") + "/sign-in") +// return c.Type("html").SendString(` +// +// +// +// +// Redirecting... +// +// +//

Redirecting to frontend...

+// +// +// +// `) } diff --git a/backend/middleware/cors_middleware.go b/backend/middleware/cors_middleware.go index 3ad65d6..7f7efd4 100644 --- a/backend/middleware/cors_middleware.go +++ b/backend/middleware/cors_middleware.go @@ -16,9 +16,12 @@ func CORSMiddleware() fiber.Handler { AllowMethods: "GET,POST,HEAD,PUT,DELETE,PATCH", AllowHeaders: "Origin, Content-Type, Accept, Authorization", // AllowOrigins: "http://localhost:3000", // Set to your frontend origin - AllowOrigins: "https://senzen-frontend.vercel.app", + // AllowOrigins: "https://senzen-frontend.vercel.app", // AllowOrigins: frontendOrigin, // AllowOrigins: "http://cashwise.com", // Set to your frontend origin - AllowCredentials: true, // Allows cookies and credentials to be sent + // AllowCredentials: true, // Allows cookies and credentials to be sent + + AllowOrigins: "https://frontend.pantorn.me", + AllowCredentials: true, }) } From 08bc6d4c952ee419f1b00ea23cc49e813507ac22 Mon Sep 17 00:00:00 2001 From: pantorn Date: Wed, 14 May 2025 18:33:12 +0700 Subject: [PATCH 06/11] update backend for oauth --- frontend/Dockerfile | 1 - .../src/app/(product)/createPlan/page.tsx | 200 +++++++++--------- frontend/src/hooks/usePlan.tsx | 8 +- 3 files changed, 104 insertions(+), 105 deletions(-) diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 1ed09c3..62d1681 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -17,7 +17,6 @@ RUN \ else echo "Lockfile not found." && exit 1; \ fi - # Rebuild the source code only when needed FROM base AS builder WORKDIR /app diff --git a/frontend/src/app/(product)/createPlan/page.tsx b/frontend/src/app/(product)/createPlan/page.tsx index 06328fa..69ae5f7 100644 --- a/frontend/src/app/(product)/createPlan/page.tsx +++ b/frontend/src/app/(product)/createPlan/page.tsx @@ -111,108 +111,108 @@ export default function CreatePlan() { />
- - -
- - -
-
- - -
-
- - -
-
+ {/* */} + {/* */} + {/*
*/} + {/* */} + {/* */} + {/*
*/} + {/*
*/} + {/* */} + {/* */} + {/*
*/} + {/*
*/} + {/* */} + {/* */} + {/*
*/} + {/*
*/} -
- - -
- -
- - -
+ {/*
*/} + {/* */} + {/* */} + {/*
*/} -
- -
- - $ - - setInitialBudget(e.target.value)} - className="pl-7" - /> -
-
- -
- - -
+ {/*
*/} + {/* */} + {/* */} + {/*
*/} + {/**/} + {/*
*/} + {/* */} + {/*
*/} + {/* */} + {/* $ */} + {/* */} + {/* setInitialBudget(e.target.value)} */} + {/* className="pl-7" */} + {/* /> */} + {/*
*/} + {/*
*/} + {/**/} + {/*
*/} + {/* */} + {/* */} + {/*
*/} - - + + + + + + + + + + + + Login with Google + + - - + + Login with GitHub +
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index ff177fd..4c7e2f6 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "ES2017", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -11,7 +15,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "incremental": true, "plugins": [ { @@ -19,11 +23,36 @@ } ], "paths": { - "@/*": ["./src/*"], - "@example*": ["./src/components/example/*"], - "@components*": ["./src/components/ui/*"], + "@/*": [ + "./src/*" + ], + "@example*": [ + "./src/components/example/*" + ], + "@components*": [ + "./src/components/ui/*" + ] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/middleware.ts.old", "src/app/api/auth/route.js", "src/app/sign-in/damn", "src/components/ui/profile-dropdown.go", "src/app/testHome/pp", "src/app/page.tsx.old", "src/app/(product)/plan/[...planId]/page.tsx.old", "src/app/(product)/plan/[...planId]/p", "src/app/(product)/plan/[...planId]/p", "src/app/not-found.old", "src/m"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "src/middleware.ts.old", + "src/app/api/auth/route.js", + "src/app/sign-in/damn", + "src/components/ui/profile-dropdown.go", + "src/app/testHome/pp", + "src/app/page.tsx.old", + "src/app/(product)/plan/[...planId]/page.tsx.old", + "src/app/(product)/plan/[...planId]/p", + "src/app/(product)/plan/[...planId]/p", + "src/app/not-found.old", + "src/m", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } From 324756aa3252e4a7dca6a15ab52f62867ef0fec1 Mon Sep 17 00:00:00 2001 From: pantorn Date: Mon, 16 Mar 2026 04:19:17 +0700 Subject: [PATCH 11/11] fix: return proper types from fetch functions on error - Changed fetchGet to return [] instead of JSX on error - Changed fetchPost to return null instead of JSX on error - Prevents .map() errors when API calls fail Co-Authored-By: Claude Opus 4.6 --- frontend/src/fetch/client.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/fetch/client.tsx b/frontend/src/fetch/client.tsx index 6a299d3..4359ee4 100644 --- a/frontend/src/fetch/client.tsx +++ b/frontend/src/fetch/client.tsx @@ -20,7 +20,7 @@ export async function fetchGet(url: string): Promise { return await res.json(); } catch (error) { console.error(error); - return
Error loading data
; + return []; // Return empty array instead of JSX } } @@ -44,7 +44,7 @@ export async function fetchPost(url: string, data: any): Promise { return await res.json(); } catch (error) { console.error(error); - return
Error loading data
; + return null; } }