From 83545fb85492648b5fca640199410f52608bda3b Mon Sep 17 00:00:00 2001 From: ysandler Date: Mon, 17 Mar 2025 17:55:17 -0500 Subject: [PATCH] feat: connect to db and sample query --- .container_volume/scripts/01_users.sql | 13 ++++++++++ .env | 3 ++- db/connection.go | 33 ++++++++++++++++------- docker-compose.yaml | 10 +++---- entities/User.go | 36 +++++++++++++------------- go.mod | 4 +-- go.sum | 4 +-- main.go | 16 ++++++++++-- repository/UserRepo.go | 10 +++---- 9 files changed, 83 insertions(+), 46 deletions(-) create mode 100644 .container_volume/scripts/01_users.sql diff --git a/.container_volume/scripts/01_users.sql b/.container_volume/scripts/01_users.sql new file mode 100644 index 0000000..8c8be72 --- /dev/null +++ b/.container_volume/scripts/01_users.sql @@ -0,0 +1,13 @@ +-- I DO NOT KNOW IF THIS WORKS -- +-- I AM PLAYING ARROUND WITH START UP SCRIPTS FOR THE CONTAINER -- + +-- Drop existing roles/users if they exist +DROP ROLE IF EXISTS admin; +DROP USER IF EXISTS admin; + +-- Create admin user with strong password using bcrypt +CREATE USER admin WITH PASSWORD 'password'; + +-- Grant all privileges +ALTER ROLE admin SUPERUSER; +GRANT ALL PRIVILEGES TO admin; diff --git a/.env b/.env index 6829ebc..54e02d1 100644 --- a/.env +++ b/.env @@ -4,5 +4,6 @@ DB_NAME=worklog DB_HOST=localhost DB_PORT=5432 DB_EXPOSED_PORT=6767 +DB_TZ=America/Chicago -VOLUME_ROOT="./container_volume" +VOLUME_ROOT="./.container_volume" diff --git a/db/connection.go b/db/connection.go index 1eacfd6..1a476db 100644 --- a/db/connection.go +++ b/db/connection.go @@ -2,8 +2,10 @@ package db import ( "fmt" + "log" "os" + "github.com/joho/godotenv" "gorm.io/driver/postgres" "gorm.io/gorm" ) @@ -11,37 +13,48 @@ import ( var DB *gorm.DB func getEnv(key string) string { - if value, ok := os.LookupEnv(key); ok { + log.Printf("Loading environment variables...") + + err := godotenv.Load() + if err != nil { + log.Fatal(fmt.Sprintf("Error loading .env file: %v", err)) + } + + value := os.Getenv(key) + if value != "" { return value } panic(fmt.Sprintf("Missing environment variable: %s", key)) } -func Init() *gorm.DB { +func Init() (*gorm.DB, error) { if DB != nil { - return DB + return DB, nil } - connectionString := fmt.Sprintf("host=%s user=%s password=%s dbname=%s host=%s port=%s TimeZone=%s", - getEnv("DB_HOST"), + log.Println("Initializing database connection...") + connectionString := fmt.Sprintf("user=%s password=%s dbname=%s host=%s port=%s TimeZone=%s", getEnv("DB_USER"), getEnv("DB_PASSWORD"), getEnv("DB_NAME"), getEnv("DB_HOST"), - getEnv("DB_PORT"), + getEnv("DB_EXPOSED_PORT"), getEnv("DB_TZ")) + + log.Printf("Database connection string: %s", connectionString) db, err := gorm.Open(postgres.Open(connectionString), &gorm.Config{}) if err != nil { - panic(fmt.Errorf("failed to connect to database: %v", err)) + return nil, err } sqlDB, err := db.DB() if err != nil { - panic(err) + return nil, err } + sqlDB.SetMaxOpenConns(10) sqlDB.SetMaxIdleConns(5) - DB = db - return DB + log.Println("Database connection established successfully") + return db, nil } diff --git a/docker-compose.yaml b/docker-compose.yaml index 2e9bce8..e05046f 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,4 +1,3 @@ -version: '3' services: postgresdb: image: postgres:latest @@ -6,15 +5,14 @@ services: ports: - "${DB_EXPOSED_PORT}:${DB_PORT}" environment: - POSTGRES_DB: ${POSTGRES_DB} - POSTGRES_USER: ${POSTGRES_USER} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: worklog + POSTGRES_USER: admin + POSTGRES_PASSWORD: password volumes: - "${VOLUME_ROOT}/db:/var/lib/postgresql/data" + - "${VOLUME_ROOT}/scripts:/docker-entrypoint-initdb.d/" env_file: - ./.env - depends_on: - - postgresdb networks: postgres-network: diff --git a/entities/User.go b/entities/User.go index ae7a88e..8426260 100644 --- a/entities/User.go +++ b/entities/User.go @@ -9,12 +9,12 @@ import ( type User struct { gorm.Model ID uuid.UUID `gorm:"type:uuid;primaryKey;default:uuid_generate_v4()"` - FirstName string - LastName string - Email string - PhoneNumber string - CreatedAt time.Time - UpdatedAt time.Time + FirstName string `gorm:"size:255"` + LastName string `gorm:"size:255"` + Email string `gorm:"unique;not null;size:255"` + PhoneNumber string `gorm:"size:255"` + CreatedAt time.Time `gorm:"default:now()"` + UpdatedAt time.Time `gorm:"default:now()"` } type DevUser struct { @@ -30,21 +30,21 @@ type ClientUser struct { type ClientUser_Project_Join struct { gorm.Model ID uuid.UUID `gorm:"type:uuid;primaryKey;default:uuid_generate_v4()"` - ClientId uuid.UUID - ProjectId uuid.UUID - CreatedAt time.Time - UpdatedAt time.Time - IsStakeholder bool - Notes string + ClientId uuid.UUID `gorm:"foreignKey:ClientId;index:clientIdProjectIndex" ` + ProjectId uuid.UUID `gorm:"foreignKey:ProjectId;index:projectIdClientIndex"` + CreatedAt time.Time `gorm:"default:now()"` + UpdatedAt time.Time `gorm:"default:now()"` + IsStakeholder bool `gorm:"size:1"` + Notes string `gorm:"type:text"` } type DevUser_Project_Join struct { gorm.Model ID uuid.UUID `gorm:"type:uuid;primaryKey;default:uuid_generate_v4()"` - ClientId uuid.UUID - ProjectId uuid.UUID - CreatedAt time.Time - UpdatedAt time.Time - IsLead bool - Notes string + ClientId uuid.UUID `gorm:"foreignKey:ClientId;index:clientIdDevIndex" ` + ProjectId uuid.UUID `gorm:"foreignKey:ProjectId;index:projectIdDevIndex"` + CreatedAt time.Time `gorm:"default:now()"` + UpdatedAt time.Time `gorm:"default:now()"` + IsLead bool `gorm:"size:1"` + Notes string `gorm:"type:text"` } diff --git a/go.mod b/go.mod index 7693504..c147c31 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,8 @@ go 1.23.2 require ( github.com/gofiber/fiber/v3 v3.0.0-beta.4 github.com/google/uuid v1.6.0 + github.com/joho/godotenv v1.5.1 + gorm.io/driver/postgres v1.5.11 gorm.io/gorm v1.25.12 ) @@ -20,7 +22,6 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/klauspost/compress v1.18.0 // indirect - github.com/lib/pq v1.10.9 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect @@ -33,5 +34,4 @@ require ( golang.org/x/sync v0.12.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect - gorm.io/driver/postgres v1.5.11 // indirect ) diff --git a/go.sum b/go.sum index 17635f2..218882f 100644 --- a/go.sum +++ b/go.sum @@ -25,10 +25,10 @@ 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.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= diff --git a/main.go b/main.go index 8c96f59..55371bf 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "log" "github.com/gofiber/fiber/v3" @@ -9,11 +10,22 @@ import ( ) func main() { - if err := db.Init(); err != nil { + DB, err := db.Init() + + if err != nil { log.Fatal(err) } - repo := repository.GetUserRepo(db.DB) + repo := repository.GetUserRepo(DB) + ctx := context.Background() + + users, totalUserCount, err := repo.List(ctx, 0, 10) + if err != nil { + log.Println(err) + } + + log.Printf("Fetched %d users", len(users)) + log.Printf("%d total users", totalUserCount) app := fiber.New() diff --git a/repository/UserRepo.go b/repository/UserRepo.go index a44e683..caa18c7 100644 --- a/repository/UserRepo.go +++ b/repository/UserRepo.go @@ -55,13 +55,13 @@ func (r *UserRepository) Delete(ctx context.Context, id uuid.UUID) error { return r.db.WithContext(ctx).Delete(&user).Error } -func (r *UserRepository) List(ctx context.Context, offset int, limit int) ([]entities.User, int64) { +func (r *UserRepository) List(ctx context.Context, offset int, limit int) ([]entities.User, int64, error) { var users []entities.User var totalUserCount int64 - query := r.db.WithContext(ctx).Model(&users).Where("1 = 1") // All Users - query.Count(&totalUserCount) // Count of All Users - query.Offset(offset).Limit(limit).Find(&users) // Filtered Users + if err := r.db.WithContext(ctx).Where("1 = 1").Count(&totalUserCount).Offset(offset).Limit(limit); err != nil { + return nil, 0, err.Error + } - return users, totalUserCount + return users, totalUserCount, nil }