package postgres import ( "context" "crypto/rand" "errors" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/snip/backend/internal/domain" ) type UserRepo struct{ pool *pgxpool.Pool } func NewUserRepo(pool *pgxpool.Pool) *UserRepo { return &UserRepo{pool: pool} } func (r *UserRepo) Upsert(ctx context.Context, u *domain.User) (*domain.User, error) { id := newUserID() var out domain.User err := r.pool.QueryRow(ctx, `INSERT INTO users (id, email, name, provider, subject) VALUES ($1,$2,$3,$4,$5) ON CONFLICT (provider, subject) DO UPDATE SET email = EXCLUDED.email, name = EXCLUDED.name RETURNING id, email, name, provider, subject`, id, u.Email, u.Name, u.Provider, u.Subject). Scan(&out.ID, &out.Email, &out.Name, &out.Provider, &out.Subject) if err != nil { return nil, err } return &out, nil } func (r *UserRepo) GetByID(ctx context.Context, id string) (*domain.User, error) { var u domain.User err := r.pool.QueryRow(ctx, `SELECT id, email, name, provider, subject FROM users WHERE id=$1`, id). Scan(&u.ID, &u.Email, &u.Name, &u.Provider, &u.Subject) if errors.Is(err, pgx.ErrNoRows) { return nil, domain.ErrNotFound } if err != nil { return nil, err } return &u, nil } func newUserID() string { const hex = "0123456789abcdef" b := make([]byte, 16) _, _ = rand.Read(b) out := make([]byte, 16) for i := range out { out[i] = hex[int(b[i])%16] } return "u_" + string(out) }