Files
skybridge/user/internal/repository/postgres/profile_repository.go
2025-08-31 22:35:23 -04:00

158 lines
4.0 KiB
Go

package postgres
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"time"
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
"github.com/RyanCopley/skybridge/user/internal/domain"
"github.com/RyanCopley/skybridge/user/internal/repository/interfaces"
)
type userProfileRepository struct {
db *sqlx.DB
}
// NewUserProfileRepository creates a new user profile repository
func NewUserProfileRepository(db *sqlx.DB) interfaces.UserProfileRepository {
return &userProfileRepository{db: db}
}
func (r *userProfileRepository) Create(ctx context.Context, profile *domain.UserProfile) error {
profile.CreatedAt = time.Now()
profile.UpdatedAt = time.Now()
// Convert preferences to JSON
var preferencesJSON []byte
if profile.Preferences != nil {
var err error
preferencesJSON, err = json.Marshal(profile.Preferences)
if err != nil {
return fmt.Errorf("failed to marshal preferences: %w", err)
}
}
query := `
INSERT INTO user_profiles (
user_id, bio, location, website, timezone, language,
preferences, created_at, updated_at
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9
)`
_, err := r.db.ExecContext(ctx, query,
profile.UserID, profile.Bio, profile.Location, profile.Website,
profile.Timezone, profile.Language, preferencesJSON,
profile.CreatedAt, profile.UpdatedAt,
)
if err != nil {
return fmt.Errorf("failed to create user profile: %w", err)
}
return nil
}
func (r *userProfileRepository) GetByUserID(ctx context.Context, userID uuid.UUID) (*domain.UserProfile, error) {
query := `
SELECT user_id, bio, location, website, timezone, language,
preferences, created_at, updated_at
FROM user_profiles
WHERE user_id = $1`
row := r.db.QueryRowContext(ctx, query, userID)
var profile domain.UserProfile
var preferencesJSON sql.NullString
err := row.Scan(
&profile.UserID, &profile.Bio, &profile.Location, &profile.Website,
&profile.Timezone, &profile.Language, &preferencesJSON,
&profile.CreatedAt, &profile.UpdatedAt,
)
if err != nil {
if err == sql.ErrNoRows {
return nil, fmt.Errorf("user profile not found")
}
return nil, fmt.Errorf("failed to get user profile: %w", err)
}
// Parse preferences JSON
if preferencesJSON.Valid && preferencesJSON.String != "" {
var preferences map[string]interface{}
err = json.Unmarshal([]byte(preferencesJSON.String), &preferences)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal preferences: %w", err)
}
profile.Preferences = preferences
}
return &profile, nil
}
func (r *userProfileRepository) Update(ctx context.Context, profile *domain.UserProfile) error {
profile.UpdatedAt = time.Now()
// Convert preferences to JSON
var preferencesJSON []byte
if profile.Preferences != nil {
var err error
preferencesJSON, err = json.Marshal(profile.Preferences)
if err != nil {
return fmt.Errorf("failed to marshal preferences: %w", err)
}
}
query := `
UPDATE user_profiles SET
bio = $2,
location = $3,
website = $4,
timezone = $5,
language = $6,
preferences = $7,
updated_at = $8
WHERE user_id = $1`
result, err := r.db.ExecContext(ctx, query,
profile.UserID, profile.Bio, profile.Location, profile.Website,
profile.Timezone, profile.Language, preferencesJSON,
profile.UpdatedAt,
)
if err != nil {
return fmt.Errorf("failed to update user profile: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("failed to get affected rows: %w", err)
}
if rowsAffected == 0 {
return fmt.Errorf("user profile not found")
}
return nil
}
func (r *userProfileRepository) Delete(ctx context.Context, userID uuid.UUID) error {
query := `DELETE FROM user_profiles WHERE user_id = $1`
result, err := r.db.ExecContext(ctx, query, userID)
if err != nil {
return fmt.Errorf("failed to delete user profile: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("failed to get affected rows: %w", err)
}
if rowsAffected == 0 {
return fmt.Errorf("user profile not found")
}
return nil
}