2026-02-25 18:49:25 +00:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
|
"gorm.io/gorm"
|
2026-03-06 23:54:35 +00:00
|
|
|
|
|
|
|
|
apperrors "veza-backend-api/internal/errors"
|
2026-02-25 18:49:25 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// PrivacyOptOut sets the CCPA "Do Not Sell" preference for the authenticated user.
|
|
|
|
|
// v0.803 SEC2-06: CCPA compliance - honors user opt-out request.
|
2026-02-25 18:51:54 +00:00
|
|
|
//
|
|
|
|
|
// @Summary CCPA Do Not Sell opt-out
|
|
|
|
|
// @Description Saves the user's Do Not Sell preference (CCPA compliance)
|
|
|
|
|
// @Tags Users
|
|
|
|
|
// @Security BearerAuth
|
|
|
|
|
// @Success 200 {object} map[string]interface{}
|
|
|
|
|
// @Failure 401 {object} map[string]interface{}
|
|
|
|
|
// @Failure 500 {object} map[string]interface{}
|
|
|
|
|
// @Router /users/me/privacy/opt-out [post]
|
2026-02-25 18:49:25 +00:00
|
|
|
func PrivacyOptOut(db *gorm.DB) gin.HandlerFunc {
|
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
|
userID, ok := GetUserIDUUID(c)
|
|
|
|
|
if !ok || userID == uuid.Nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewUnauthorizedError("Authentication required"))
|
2026-02-25 18:49:25 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Upsert user_preferences with do_not_sell in privacy JSONB
|
|
|
|
|
// Uses PostgreSQL jsonb_set to merge do_not_sell: true into existing privacy
|
|
|
|
|
result := db.Exec(`
|
|
|
|
|
INSERT INTO user_preferences (user_id, theme, language, timezone, notifications, privacy, audio, contrast, density, accent_hue, font_size, updated_at)
|
|
|
|
|
VALUES ($1, 'light', 'en', 'UTC', '{}', '{"do_not_sell": true}', '{}', 'normal', 'comfortable', 220, 16, NOW())
|
|
|
|
|
ON CONFLICT (user_id) DO UPDATE SET
|
|
|
|
|
privacy = COALESCE(user_preferences.privacy, '{}')::jsonb || '{"do_not_sell": true}'::jsonb,
|
|
|
|
|
updated_at = NOW()
|
|
|
|
|
`, userID)
|
|
|
|
|
|
|
|
|
|
if result.Error != nil {
|
2026-03-06 23:54:35 +00:00
|
|
|
RespondWithAppError(c, apperrors.NewInternalErrorWrap("Failed to save privacy preference", result.Error))
|
2026-02-25 18:49:25 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RespondSuccess(c, http.StatusOK, gin.H{"message": "Do Not Sell preference saved"})
|
|
|
|
|
}
|
|
|
|
|
}
|