Compare commits

...

6 commits

Author SHA1 Message Date
Cipher Vance
daa90869cf feat: update email verification 2025-09-18 21:04:16 -05:00
Cipher Vance
afd12684b6 removed testing comment 2025-09-18 21:03:49 -05:00
Cipher Vance
7620a938f5 docs: formatting issues 2025-09-18 21:03:38 -05:00
Cipher Vance
56c8d3a786 feat: make secret key a little more potent 2025-09-18 21:03:28 -05:00
Cipher Vance
a32b2a4210 feat: add some basic folders 2025-09-18 21:03:06 -05:00
Cipher Vance
18b6f74ab5 feat: add database ping 2025-09-18 21:02:57 -05:00
5 changed files with 55 additions and 13 deletions

View file

@ -9,4 +9,11 @@ tmp/
.idea/
*.log
coverage.out
rideaware-api
rideaware-api
__pycache__/
*.py[cod]
.venv/
venv/
dist/
build/
node_modules/

View file

@ -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

View file

@ -4,6 +4,7 @@ import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/postgres"
"gorm.io/gorm"
@ -16,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)
@ -24,5 +24,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
}

19
main.go
View file

@ -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) {

View file

@ -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
}