package db import ( "context" "time" "golang.org/x/crypto/bcrypt" ) type User struct { ID int `json:"id"` Username string `json:"username"` PasswordHash string `json:"-"` CreatedAt time.Time `json:"created_at"` } type CreateUserRequest struct { Username string `json:"username"` Password string `json:"password"` } type LoginRequest struct { Username string `json:"username"` Password string `json:"password"` } func CreateUser(ctx context.Context, req CreateUserRequest) (*User, error) { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) if err != nil { return nil, err } var user User err = Pool.QueryRow(ctx, "INSERT INTO users (username, password_hash) VALUES ($1, $2) RETURNING id, username, created_at", req.Username, string(hashedPassword), ).Scan(&user.ID, &user.Username, &user.CreatedAt) if err != nil { return nil, err } return &user, nil } func GetUserByUsername(ctx context.Context, username string) (*User, error) { var user User err := Pool.QueryRow(ctx, "SELECT id, username, password_hash, created_at FROM users WHERE username = $1", username, ).Scan(&user.ID, &user.Username, &user.PasswordHash, &user.CreatedAt) if err != nil { return nil, err } return &user, nil } func ValidateUserCredentials(ctx context.Context, username, password string) (*User, error) { user, err := GetUserByUsername(ctx, username) if err != nil { return nil, err } err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password)) if err != nil { return nil, err } return user, nil }