veza/veza-backend-api/internal/handlers/settings_handler.go

146 lines
4.4 KiB
Go

package handlers
import (
"fmt"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"go.uber.org/zap"
"veza-backend-api/internal/services"
"veza-backend-api/internal/types"
)
// SettingsHandler handles settings-related operations
type SettingsHandler struct {
userService *services.UserService
commonHandler *CommonHandler
}
// NewSettingsHandler creates a new SettingsHandler instance
func NewSettingsHandler(userService *services.UserService, logger *zap.Logger) *SettingsHandler {
return &SettingsHandler{
userService: userService,
commonHandler: NewCommonHandler(logger),
}
}
// UserSettingsResponse represents the response structure for user settings
type UserSettingsResponse struct {
Notifications NotificationSettings `json:"notifications"`
Privacy PrivacySettings `json:"privacy"`
Content ContentSettings `json:"content"`
Preferences PreferenceSettings `json:"preferences"`
}
// NotificationSettings represents notification preferences
type NotificationSettings struct {
EmailNotifications bool `json:"email_notifications"`
PushNotifications bool `json:"push_notifications"`
BrowserNotifications bool `json:"browser_notifications"`
EmailOnFollow bool `json:"email_on_follow"`
EmailOnLike bool `json:"email_on_like"`
EmailOnComment bool `json:"email_on_comment"`
EmailOnMessage bool `json:"email_on_message"`
EmailOnMention bool `json:"email_on_mention"`
EmailMarketing bool `json:"email_marketing"`
}
// PrivacySettings represents privacy preferences
type PrivacySettings struct {
AllowSearchIndexing bool `json:"allow_search_indexing"`
ShowActivity bool `json:"show_activity"`
}
// ContentSettings represents content preferences
type ContentSettings struct {
ExplicitContent bool `json:"explicit_content"`
Autoplay bool `json:"autoplay"`
}
// PreferenceSettings represents user preferences
type PreferenceSettings struct {
Language string `json:"language"` // ISO 639-1
Timezone string `json:"timezone"`
Theme string `json:"theme"` // light, dark, auto
}
// GetSettings retrieves user settings
// T0231: Utilise l'utilisateur authentifié depuis le contexte (route /users/settings sans :id)
func (h *SettingsHandler) GetSettings(c *gin.Context) {
// Récupérer l'ID utilisateur depuis le contexte d'authentification
userID := c.MustGet("user_id").(uuid.UUID)
if userID == uuid.Nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
return
}
settings, err := h.userService.GetUserSettings(userID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get settings"})
return
}
RespondSuccess(c, http.StatusOK, settings)
}
// UpdateSettings updates user settings
// T0232: Utilise l'utilisateur authentifié depuis le contexte (route /users/settings sans :id)
func (h *SettingsHandler) UpdateSettings(c *gin.Context) {
// Récupérer l'ID utilisateur depuis le contexte d'authentification
userID := c.MustGet("user_id").(uuid.UUID)
if userID == uuid.Nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
return
}
var req types.UpdateSettingsRequest
if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
RespondWithAppError(c, appErr)
return
}
// Valider preferences si fournies
if req.Preferences != nil {
if err := h.validatePreferences(req.Preferences); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
}
// Mettre à jour settings
if err := h.userService.UpdateUserSettings(userID, &req); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update settings"})
return
}
RespondSuccess(c, http.StatusOK, gin.H{"message": "settings updated"})
}
// validatePreferences validates preference settings
func (h *SettingsHandler) validatePreferences(prefs *types.PreferenceSettings) error {
// Valider language (ISO 639-1)
validLanguages := []string{"en", "fr", "es", "de", "it", "pt", "ru", "ja", "zh", "ko"}
if prefs.Language != "" {
valid := false
for _, lang := range validLanguages {
if prefs.Language == lang {
valid = true
break
}
}
if !valid {
return fmt.Errorf("invalid language code: %s", prefs.Language)
}
}
// Valider timezone (IANA timezone)
if prefs.Timezone != "" {
if _, err := time.LoadLocation(prefs.Timezone); err != nil {
return fmt.Errorf("invalid timezone: %s", prefs.Timezone)
}
}
return nil
}