A community based topic aggregation platform built on atproto
1package postgres 2 3import ( 4 "Coves/internal/core/users" 5 "context" 6 "database/sql" 7 "fmt" 8 "strings" 9) 10 11type postgresUserRepo struct { 12 db *sql.DB 13} 14 15// NewUserRepository creates a new PostgreSQL user repository 16func NewUserRepository(db *sql.DB) users.UserRepository { 17 return &postgresUserRepo{db: db} 18} 19 20// Create inserts a new user into the users table 21func (r *postgresUserRepo) Create(ctx context.Context, user *users.User) (*users.User, error) { 22 query := ` 23 INSERT INTO users (did, handle, pds_url) 24 VALUES ($1, $2, $3) 25 RETURNING did, handle, pds_url, created_at, updated_at` 26 27 err := r.db.QueryRowContext(ctx, query, user.DID, user.Handle, user.PDSURL). 28 Scan(&user.DID, &user.Handle, &user.PDSURL, &user.CreatedAt, &user.UpdatedAt) 29 if err != nil { 30 // Check for unique constraint violations 31 if strings.Contains(err.Error(), "duplicate key") { 32 if strings.Contains(err.Error(), "users_pkey") { 33 return nil, fmt.Errorf("user with DID already exists") 34 } 35 if strings.Contains(err.Error(), "users_handle_key") { 36 return nil, fmt.Errorf("handle already taken") 37 } 38 } 39 return nil, fmt.Errorf("failed to create user: %w", err) 40 } 41 42 return user, nil 43} 44 45// GetByDID retrieves a user by their DID 46func (r *postgresUserRepo) GetByDID(ctx context.Context, did string) (*users.User, error) { 47 user := &users.User{} 48 query := `SELECT did, handle, pds_url, created_at, updated_at FROM users WHERE did = $1` 49 50 err := r.db.QueryRowContext(ctx, query, did). 51 Scan(&user.DID, &user.Handle, &user.PDSURL, &user.CreatedAt, &user.UpdatedAt) 52 53 if err == sql.ErrNoRows { 54 return nil, fmt.Errorf("user not found") 55 } 56 if err != nil { 57 return nil, fmt.Errorf("failed to get user by DID: %w", err) 58 } 59 60 return user, nil 61} 62 63// GetByHandle retrieves a user by their handle 64func (r *postgresUserRepo) GetByHandle(ctx context.Context, handle string) (*users.User, error) { 65 user := &users.User{} 66 query := `SELECT did, handle, pds_url, created_at, updated_at FROM users WHERE handle = $1` 67 68 err := r.db.QueryRowContext(ctx, query, handle). 69 Scan(&user.DID, &user.Handle, &user.PDSURL, &user.CreatedAt, &user.UpdatedAt) 70 71 if err == sql.ErrNoRows { 72 return nil, fmt.Errorf("user not found") 73 } 74 if err != nil { 75 return nil, fmt.Errorf("failed to get user by handle: %w", err) 76 } 77 78 return user, nil 79} 80 81// UpdateHandle updates the handle for a user with the given DID 82func (r *postgresUserRepo) UpdateHandle(ctx context.Context, did, newHandle string) (*users.User, error) { 83 user := &users.User{} 84 query := ` 85 UPDATE users 86 SET handle = $2, updated_at = NOW() 87 WHERE did = $1 88 RETURNING did, handle, pds_url, created_at, updated_at` 89 90 err := r.db.QueryRowContext(ctx, query, did, newHandle). 91 Scan(&user.DID, &user.Handle, &user.PDSURL, &user.CreatedAt, &user.UpdatedAt) 92 93 if err == sql.ErrNoRows { 94 return nil, fmt.Errorf("user not found") 95 } 96 if err != nil { 97 // Check for unique constraint violation on handle 98 if strings.Contains(err.Error(), "duplicate key") && strings.Contains(err.Error(), "users_handle_key") { 99 return nil, fmt.Errorf("handle already taken") 100 } 101 return nil, fmt.Errorf("failed to update handle: %w", err) 102 } 103 104 return user, nil 105}