From 18b6f74ab55fcaa0069a60eb40737e2cb5ec35e3 Mon Sep 17 00:00:00 2001 From: Cipher Vance Date: Thu, 18 Sep 2025 21:02:57 -0500 Subject: [PATCH 1/6] feat: add database ping --- config/database.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/config/database.go b/config/database.go index be6ad8e..2b6b5f0 100644 --- a/config/database.go +++ b/config/database.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "os" + "time" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -24,5 +25,19 @@ func InitDB() *gorm.DB { if err != nil { log.Fatal("Failed to connect to database:", err) } + + sqlDB, err := db.DB() + if err != nil { + log.Fatal("Failed to get sql.DB from gorm:", err) + } + + sqlDB.SetMaxOpenConns(25) + sqlDB.SetMaxIdleConns(25) + sqlDB.SetConnMaxLifetime(30 * time.Minute) + + if err != nil { + log.Fatal("Database ping failed:", err) + } + return db } From a32b2a4210ed2b2719b2f5d201aad20afae64ac0 Mon Sep 17 00:00:00 2001 From: Cipher Vance Date: Thu, 18 Sep 2025 21:03:06 -0500 Subject: [PATCH 2/6] feat: add some basic folders --- .dockerignore | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.dockerignore b/.dockerignore index ccbe03a..36ad821 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,4 +9,11 @@ tmp/ .idea/ *.log coverage.out -rideaware-api \ No newline at end of file +rideaware-api +__pycache__/ +*.py[cod] +.venv/ +venv/ +dist/ +build/ +node_modules/ \ No newline at end of file From 56c8d3a7861b9d6a9fa7cb9507b2e38db8053f1d Mon Sep 17 00:00:00 2001 From: Cipher Vance Date: Thu, 18 Sep 2025 21:03:28 -0500 Subject: [PATCH 3/6] feat: make secret key a little more potent --- main.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 8128f9f..215c2a6 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "log" + "net/http" "os" "github.com/gin-contrib/cors" @@ -36,8 +37,22 @@ func main() { r.Use(cors.Default()) // Session middleware - store := cookie.NewStore([]byte(os.Getenv("SECRET_KEY"))) - r.Use(sessions.Sessions("session", store)) + secret := os.Getenv("SECRET_KEY") + if len(secret) < 32 { + log.Fatal("SECRET_KEY must be at least 32 bytes") + } + + authKey := []byte(secret) + encKey := []byte(secret[:32]) + store := cookie.NewStore(authKey, encKey) + store.Options(sessions.Options{ + Path: "/", + MaxAge: 60 * 80 * 24 * 7, // 7 days + HttpOnly: true, + Secure: os.Getenv("ENV") == "production", + SameSite: http.SameSiteLaxMode, + }) + r.Use(sessions.Sessions("rideaware-session", store)) // Health check endpoint r.GET("/health", func(c *gin.Context) { From 7620a938f5fef954d645c86cc91198e4e5467abc Mon Sep 17 00:00:00 2001 From: Cipher Vance Date: Thu, 18 Sep 2025 21:03:38 -0500 Subject: [PATCH 4/6] docs: formatting issues --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 65ce1b9..d8f01d3 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Ensure you have the following installed on your system: 2. **Install Go Dependencies** - ```bash + ```bash go mod tidy ``` @@ -51,8 +51,10 @@ PG_USER=your_postgres_user PG_PASSWORD=your_postgres_password # Application Configuration +# SECRET_KEY should be a random 32+ byte string; rotate on compromise. SECRET_KEY=your_secret_key_for_sessions PORT=8080 +PG_SSLMODE=require # use "disable" only for local dev # Email Configuration (Optional) SMTP_SERVER=your_smtp_server @@ -69,7 +71,7 @@ SMTP_PASSWORD=your_email_password go run main.go ``` -The application will be available at http://localhost:8080. +The application will be available at [http://localhost:8080](http://localhost:8080). #### Production Mode @@ -100,7 +102,7 @@ docker build -t rideaware-api . docker run -d -p 8080:8080 --env-file .env rideaware-api ``` -The application will be available at http://localhost:8080. +The application will be available at [http://localhost:8080](http://localhost:8080). ### Example Dockerfile From afd12684b66aabd89cb69f32795829ce812e257d Mon Sep 17 00:00:00 2001 From: Cipher Vance Date: Thu, 18 Sep 2025 21:03:49 -0500 Subject: [PATCH 5/6] removed testing comment --- config/database.go | 1 - 1 file changed, 1 deletion(-) diff --git a/config/database.go b/config/database.go index 2b6b5f0..f6f72b3 100644 --- a/config/database.go +++ b/config/database.go @@ -17,7 +17,6 @@ func InitDB() *gorm.DB { user := os.Getenv("PG_USER") password := os.Getenv("PG_PASSWORD") - // Try with quoted password dsn := fmt.Sprintf(`host=%s port=%s user=%s password='%s' dbname=%s sslmode=disable`, host, port, user, password, database) From daa90869cf6a13f5d47f68b89a5bd435f0271902 Mon Sep 17 00:00:00 2001 From: Cipher Vance Date: Thu, 18 Sep 2025 21:04:16 -0500 Subject: [PATCH 6/6] feat: update email verification --- services/user_service.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/services/user_service.go b/services/user_service.go index 1640cb4..c34d8a4 100644 --- a/services/user_service.go +++ b/services/user_service.go @@ -3,6 +3,7 @@ package services import ( "errors" "log" + "net/mail" "strings" "github.com/rideaware/rideaware-api/models" @@ -27,7 +28,7 @@ func (s *UserService) CreateUser(username, email, password string) (*models.User } // Basic email validation - if !strings.Contains(email, "@") { + if _, err := mail.ParseAddress(email); err != nil { return nil, errors.New("invalid email format") } @@ -57,17 +58,20 @@ func (s *UserService) CreateUser(username, email, password string) (*models.User func (s *UserService) VerifyUser(username, password string) (*models.User, error) { var user models.User - // Allow login with either username or email - if err := s.db.Where("username = ? OR email = ?", username, username).First(&user).Error; err != nil { - log.Printf("User not found: %s", username) + identifier := strings.TrimSpace(username) + if err := s.db.Where("username = ? OR email = ?", identifier, strings.ToLower(identifier)).First(&user).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, errors.New("invalid username or password") + } + log.Printf("DB error during VerifyUser: %v", err) return nil, errors.New("invalid username or password") } if !user.CheckPassword(password) { - log.Printf("Invalid password for user: %s", username) + log.Printf("Invalid credentials") return nil, errors.New("invalid username or password") } - log.Printf("User verified: %s", username) + log.Printf("User login succeeded") return &user, nil }