user_store.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package postgres
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "github.com/jackc/pgx/v5"
  7. )
  8. type User struct {
  9. ID string
  10. PublicID string
  11. Status string
  12. Nickname *string
  13. AvatarURL *string
  14. }
  15. type CreateUserParams struct {
  16. PublicID string
  17. Status string
  18. }
  19. type queryRower interface {
  20. QueryRow(context.Context, string, ...any) pgx.Row
  21. }
  22. func (s *Store) FindUserByMobile(ctx context.Context, tx Tx, countryCode, mobile string) (*User, error) {
  23. row := tx.QueryRow(ctx, `
  24. SELECT u.id, u.user_public_id, u.status, u.nickname, u.avatar_url
  25. FROM users u
  26. JOIN login_identities li ON li.user_id = u.id
  27. WHERE li.provider = 'mobile'
  28. AND li.country_code = $1
  29. AND li.mobile = $2
  30. AND li.status = 'active'
  31. LIMIT 1
  32. `, countryCode, mobile)
  33. return scanUser(row)
  34. }
  35. func (s *Store) CreateUser(ctx context.Context, tx Tx, params CreateUserParams) (*User, error) {
  36. row := tx.QueryRow(ctx, `
  37. INSERT INTO users (user_public_id, status)
  38. VALUES ($1, $2)
  39. RETURNING id, user_public_id, status, nickname, avatar_url
  40. `, params.PublicID, params.Status)
  41. return scanUser(row)
  42. }
  43. func (s *Store) TouchUserLogin(ctx context.Context, tx Tx, userID string) error {
  44. _, err := tx.Exec(ctx, `
  45. UPDATE users
  46. SET last_login_at = NOW()
  47. WHERE id = $1
  48. `, userID)
  49. if err != nil {
  50. return fmt.Errorf("touch user last login: %w", err)
  51. }
  52. return nil
  53. }
  54. func (s *Store) DeactivateUser(ctx context.Context, tx Tx, userID string) error {
  55. _, err := tx.Exec(ctx, `
  56. UPDATE users
  57. SET status = 'deleted', updated_at = NOW()
  58. WHERE id = $1
  59. `, userID)
  60. if err != nil {
  61. return fmt.Errorf("deactivate user: %w", err)
  62. }
  63. return nil
  64. }
  65. func (s *Store) GetUserByID(ctx context.Context, db queryRower, userID string) (*User, error) {
  66. row := db.QueryRow(ctx, `
  67. SELECT id, user_public_id, status, nickname, avatar_url
  68. FROM users
  69. WHERE id = $1
  70. `, userID)
  71. return scanUser(row)
  72. }
  73. func scanUser(row pgx.Row) (*User, error) {
  74. var user User
  75. err := row.Scan(&user.ID, &user.PublicID, &user.Status, &user.Nickname, &user.AvatarURL)
  76. if errors.Is(err, pgx.ErrNoRows) {
  77. return nil, nil
  78. }
  79. if err != nil {
  80. return nil, fmt.Errorf("scan user: %w", err)
  81. }
  82. return &user, nil
  83. }