buhapp-backend/internal/users/repo.go
ga 8d754f9834 Sprint 1: scaffold backend (Go + Fiber + PG + Redis + MinIO)
- POST /api/v1/auth/register with mandatory consents
- POST /api/v1/auth/login
- GET  /api/v1/me (protected)
- GET  /api/v1/legal/{terms,privacy,disclaimer}
- Migrations for users, consent_log, audit_log
- bcrypt + JWT (access + refresh)
- Docker Compose stack
2026-08-20 15:41:05 +00:00

104 lines
2.5 KiB
Go

package users
import (
"context"
"errors"
"time"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
)
type User struct {
ID uuid.UUID
Email string
Phone string
Name string
Birthdate *time.Time
Gender string
City string
Bio string
PhotoURL string
IsVerified bool
IsBlocked bool
CreatedAt time.Time
UpdatedAt time.Time
LastSeenAt *time.Time
}
type Repo struct {
pool *pgxpool.Pool
}
func NewRepo(pool *pgxpool.Pool) *Repo {
return &Repo{pool: pool}
}
func (r *Repo) CreateWithPassword(ctx context.Context, u *User, passwordHash string) error {
return r.pool.QueryRow(ctx, `
INSERT INTO users (email, phone, password_hash, name, birthdate, gender, city)
VALUES (NULLIF($1, ''), NULLIF($2, ''), $3, $4, $5, NULLIF($6, ''), NULLIF($7, ''))
RETURNING id, created_at, updated_at`,
u.Email, u.Phone, passwordHash, u.Name, u.Birthdate, u.Gender, u.City,
).Scan(&u.ID, &u.CreatedAt, &u.UpdatedAt)
}
func (r *Repo) GetByID(ctx context.Context, id uuid.UUID) (*User, error) {
u := &User{}
var email, phone, gender, city, bio, photo *string
err := r.pool.QueryRow(ctx, `
SELECT id, email, phone, name, birthdate, gender, city, bio, photo_url,
is_verified, is_blocked, created_at, updated_at, last_seen_at
FROM users WHERE id=$1`, id,
).Scan(&u.ID, &email, &phone, &u.Name, &u.Birthdate, &gender, &city, &bio, &photo,
&u.IsVerified, &u.IsBlocked, &u.CreatedAt, &u.UpdatedAt, &u.LastSeenAt)
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
if err != nil {
return nil, err
}
if email != nil {
u.Email = *email
}
if phone != nil {
u.Phone = *phone
}
if gender != nil {
u.Gender = *gender
}
if city != nil {
u.City = *city
}
if bio != nil {
u.Bio = *bio
}
if photo != nil {
u.PhotoURL = *photo
}
return u, nil
}
func (r *Repo) GetByEmail(ctx context.Context, email string) (*User, string, error) {
u := &User{}
var hash string
var em *string
err := r.pool.QueryRow(ctx, `
SELECT id, email, password_hash, name, birthdate, gender, city, bio, photo_url,
is_verified, is_blocked, created_at, updated_at, last_seen_at
FROM users WHERE email=$1`, email,
).Scan(&u.ID, &em, &hash, &u.Name, &u.Birthdate, &u.Gender, &u.City, &u.Bio, &u.PhotoURL,
&u.IsVerified, &u.IsBlocked, &u.CreatedAt, &u.UpdatedAt, &u.LastSeenAt)
if errors.Is(err, pgx.ErrNoRows) {
return nil, "", nil
}
if err != nil {
return nil, "", err
}
if em != nil {
u.Email = *em
}
return u, hash, nil
}