users.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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) HasSuperadmin(ctx context.Context) (bool, error) {
  58. count, err := r.CountByRole(ctx, "superadmin")
  59. if err != nil {
  60. return false, err
  61. }
  62. return count > 0, nil
  63. }
  64. func (r *UserRepo) CountByRole(ctx context.Context, role string) (int, error) {
  65. var count int
  66. err := r.pool.QueryRow(ctx,
  67. `SELECT COUNT(*) FROM users WHERE role = $1 AND deleted_at IS NULL`, role,
  68. ).Scan(&count)
  69. if err != nil {
  70. return 0, fmt.Errorf("count by role: %w", err)
  71. }
  72. return count, nil
  73. }
  74. func (r *UserRepo) List(ctx context.Context, filter models.UserFilter) ([]*models.User, error) {
  75. query := `SELECT id, email, password_hash, role, status, name, avatar_url, phone, bio, country,
  76. created_at, updated_at, deleted_at
  77. FROM users WHERE deleted_at IS NULL`
  78. args := pgx.NamedArgs{}
  79. if filter.Role != "" {
  80. query += ` AND role = @role`
  81. args["role"] = filter.Role
  82. }
  83. if filter.Status != "" {
  84. query += ` AND status = @status`
  85. args["status"] = filter.Status
  86. }
  87. query += ` ORDER BY created_at DESC LIMIT @lim`
  88. args["lim"] = filter.Limit()
  89. rows, err := r.pool.Query(ctx, query, args)
  90. if err != nil {
  91. return nil, fmt.Errorf("list users: %w", err)
  92. }
  93. defer rows.Close()
  94. var users []*models.User
  95. for rows.Next() {
  96. u, err := scanUser(rows)
  97. if err != nil {
  98. return nil, err
  99. }
  100. users = append(users, u)
  101. }
  102. return users, nil
  103. }
  104. func scanUser(row interface{ Scan(dest ...any) error }) (*models.User, error) {
  105. var u models.User
  106. err := row.Scan(
  107. &u.ID, &u.Email, &u.PasswordHash, &u.Role, &u.Status,
  108. &u.Name, &u.AvatarURL, &u.Phone, &u.Bio, &u.Country,
  109. &u.CreatedAt, &u.UpdatedAt, &u.DeletedAt,
  110. )
  111. if err != nil {
  112. if err == pgx.ErrNoRows {
  113. return nil, nil
  114. }
  115. return nil, err
  116. }
  117. return &u, nil
  118. }