users.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Package repository
  2. package repository
  3. import (
  4. "context"
  5. "fmt"
  6. "time"
  7. "github.com/jackc/pgx/v5"
  8. "github.com/jackc/pgx/v5/pgxpool"
  9. "gogs.fxtmmsk.ru/foxtime/photoplaces/backend/internal/models"
  10. )
  11. type UserRepo struct {
  12. pool *pgxpool.Pool
  13. }
  14. func NewUserRepo(pool *pgxpool.Pool) *UserRepo {
  15. return &UserRepo{pool: pool}
  16. }
  17. func (r *UserRepo) Create(ctx context.Context, u *models.User) error {
  18. return r.pool.QueryRow(ctx,
  19. `INSERT INTO users (email, password_hash, role, name)
  20. VALUES ($1, $2, $3, $4)
  21. RETURNING id, created_at, updated_at`,
  22. u.Email, u.PasswordHash, u.Role, u.Name,
  23. ).Scan(&u.ID, &u.CreatedAt, &u.UpdatedAt)
  24. }
  25. func (r *UserRepo) GetByID(ctx context.Context, id string) (*models.User, error) {
  26. row := r.pool.QueryRow(ctx,
  27. `SELECT id, email, password_hash, role, status, name, avatar_url, phone, bio, country,
  28. created_at, updated_at, deleted_at
  29. FROM users WHERE id = $1 AND deleted_at IS NULL`, id)
  30. return scanUser(row)
  31. }
  32. func (r *UserRepo) GetByEmail(ctx context.Context, email string) (*models.User, error) {
  33. row := r.pool.QueryRow(ctx,
  34. `SELECT id, email, password_hash, role, status, name, avatar_url, phone, bio, country,
  35. created_at, updated_at, deleted_at
  36. FROM users WHERE email = $1 AND deleted_at IS NULL`, email)
  37. return scanUser(row)
  38. }
  39. func (r *UserRepo) Update(ctx context.Context, u *models.User) error {
  40. u.UpdatedAt = time.Now()
  41. _, err := r.pool.Exec(ctx,
  42. `UPDATE users SET name=$1, phone=$2, bio=$3, avatar_url=$4, country=$5, updated_at=$6
  43. WHERE id=$7 AND deleted_at IS NULL`,
  44. u.Name, u.Phone, u.Bio, u.AvatarURL, u.Country, u.UpdatedAt, u.ID)
  45. return err
  46. }
  47. func (r *UserRepo) UpdateRole(ctx context.Context, id, role string) error {
  48. _, err := r.pool.Exec(ctx,
  49. `UPDATE users SET role=$1, updated_at=now() WHERE id=$2 AND deleted_at IS NULL`, role, id)
  50. return err
  51. }
  52. func (r *UserRepo) UpdateStatus(ctx context.Context, id, status string) error {
  53. _, err := r.pool.Exec(ctx,
  54. `UPDATE users SET status=$1, updated_at=now() WHERE id=$2 AND deleted_at IS NULL`, status, id)
  55. return err
  56. }
  57. func (r *UserRepo) List(ctx context.Context, filter models.UserFilter) ([]*models.User, error) {
  58. query := `SELECT id, email, password_hash, role, status, name, avatar_url, phone, bio, country,
  59. created_at, updated_at, deleted_at
  60. FROM users WHERE deleted_at IS NULL`
  61. args := pgx.NamedArgs{}
  62. if filter.Role != "" {
  63. query += ` AND role = @role`
  64. args["role"] = filter.Role
  65. }
  66. if filter.Status != "" {
  67. query += ` AND status = @status`
  68. args["status"] = filter.Status
  69. }
  70. query += ` ORDER BY created_at DESC LIMIT @lim`
  71. args["lim"] = filter.Limit()
  72. rows, err := r.pool.Query(ctx, query, args)
  73. if err != nil {
  74. return nil, fmt.Errorf("list users: %w", err)
  75. }
  76. defer rows.Close()
  77. var users []*models.User
  78. for rows.Next() {
  79. u, err := scanUser(rows)
  80. if err != nil {
  81. return nil, err
  82. }
  83. users = append(users, u)
  84. }
  85. return users, nil
  86. }
  87. func scanUser(row interface{ Scan(dest ...any) error }) (*models.User, error) {
  88. var u models.User
  89. err := row.Scan(
  90. &u.ID, &u.Email, &u.PasswordHash, &u.Role, &u.Status,
  91. &u.Name, &u.AvatarURL, &u.Phone, &u.Bio, &u.Country,
  92. &u.CreatedAt, &u.UpdatedAt, &u.DeletedAt,
  93. )
  94. if err != nil {
  95. if err == pgx.ErrNoRows {
  96. return nil, nil
  97. }
  98. return nil, err
  99. }
  100. return &u, nil
  101. }