veza/veza-backend-api/internal/api/user/handler.go
2025-12-03 20:29:37 +01:00

357 lines
8.4 KiB
Go

// veza-backend-api/internal/api/user/handler.go
package user
import (
"net/http"
"strconv"
"veza-backend-api/internal/common"
"veza-backend-api/internal/response"
"github.com/gin-gonic/gin"
"github.com/google/uuid" // Added import
)
type Handler struct {
service *Service
}
func NewHandler(service *Service) *Handler {
return &Handler{service: service}
}
// GetMe récupère le profil de l'utilisateur connecté
func (h *Handler) GetMe(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
user, err := h.service.GetUserByID(userID)
if err != nil {
response.NotFound(c, "User not found")
return
}
response.Success(c, user)
}
// UpdateMe met à jour le profil de l'utilisateur connecté
func (h *Handler) UpdateMe(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
var req UpdateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request data")
return
}
user, err := h.service.UpdateUser(userID, req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Success(c, user)
}
// ChangePassword change le mot de passe de l'utilisateur
func (h *Handler) ChangePassword(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
var req struct {
CurrentPassword string `json:"current_password" binding:"required"`
NewPassword string `json:"new_password" binding:"required,min=8"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request data")
return
}
err := h.service.ChangePassword(userID, req.CurrentPassword, req.NewPassword)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Success(c, nil)
}
// GetUsers liste tous les utilisateurs
func (h *Handler) GetUsers(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
search := c.Query("search")
users, total, err := h.service.GetUsers(page, limit, search)
if err != nil {
response.InternalServerError(c, "Failed to retrieve users")
return
}
response.Success(c, gin.H{
"data": users,
"pagination": gin.H{
"page": page,
"limit": limit,
"total": total,
"total_pages": (total + limit - 1) / limit,
},
})
}
// GetUsersExceptMe liste tous les utilisateurs sauf l'utilisateur connecté
func (h *Handler) GetUsersExceptMe(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
search := c.Query("search")
// Ajouter le filtre pour exclure l'utilisateur actuel
users, total, err := h.service.GetUsers(page, limit, search)
if err != nil {
response.InternalServerError(c, "Failed to retrieve users")
return
}
// Filtrer l'utilisateur connecté
filteredUsers := []UserResponse{}
for _, user := range users {
if user.ID != userID { // Direct comparison of uuid.UUID
filteredUsers = append(filteredUsers, user)
}
}
response.Success(c, gin.H{
"data": filteredUsers,
"pagination": gin.H{
"page": page,
"limit": limit,
"total": total - 1, // -1 car on exclut l'utilisateur connecté
"total_pages": (total + limit - 2) / limit,
},
})
}
// SearchUsers recherche des utilisateurs
func (h *Handler) SearchUsers(c *gin.Context) {
query := c.Query("q")
if query == "" {
response.BadRequest(c, "Query parameter 'q' is required")
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
users, total, err := h.service.GetUsers(page, limit, query)
if err != nil {
response.InternalServerError(c, "Failed to search users")
return
}
response.Success(c, gin.H{
"data": users,
"pagination": gin.H{
"page": page,
"limit": limit,
"total": total,
"total_pages": (total + limit - 1) / limit,
},
})
}
func (h *Handler) GetUserAvatar(c *gin.Context) {
idStr := c.Param("id")
userID, err := uuid.Parse(idStr)
if err != nil {
response.BadRequest(c, "Invalid user ID")
return
}
user, err := h.service.GetUserByID(userID)
if err != nil {
response.NotFound(c, "User not found")
return
}
// ✅ Correct way to handle sql.NullString
if !user.Avatar.Valid || user.Avatar.String == "" {
response.NotFound(c, "No avatar found")
return
}
// Rediriger vers l'URL de l'avatar ou servir le fichier
c.Redirect(http.StatusFound, user.Avatar.String)
}
// GetPreferences récupère les préférences de l'utilisateur connecté
func (h *Handler) GetPreferences(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
preferences, err := h.service.GetUserPreferences(userID)
if err != nil {
response.InternalServerError(c, "Failed to get preferences")
return
}
response.Success(c, preferences)
}
// UpdatePreferences met à jour les préférences de l'utilisateur connecté
func (h *Handler) UpdatePreferences(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
var req UserPreferencesRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request data")
return
}
preferences, err := h.service.UpdateUserPreferences(userID, req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Success(c, preferences)
}
// DeleteAccount supprime le compte de l'utilisateur (soft delete)
func (h *Handler) DeleteAccount(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
var req struct {
Password string `json:"password" binding:"required"`
Reason string `json:"reason"`
ConfirmText string `json:"confirm_text" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request data")
return
}
// Vérifier le texte de confirmation
if req.ConfirmText != "DELETE" {
response.BadRequest(c, "Confirmation text must be 'DELETE'")
return
}
err := h.service.DeleteAccount(userID, req.Password, req.Reason)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Success(c, nil)
}
// RecoverAccount récupère un compte supprimé
func (h *Handler) RecoverAccount(c *gin.Context) {
var req struct {
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request data")
return
}
err := h.service.RecoverAccount(req.Email, req.Password)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Success(c, nil)
}
// ExportData exporte les données de l'utilisateur (RGPD)
func (h *Handler) ExportData(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
exportData, err := h.service.ExportUserData(userID)
if err != nil {
response.InternalServerError(c, "Failed to export user data")
return
}
response.Success(c, exportData)
}
// RequestDataDeletion demande la suppression définitive des données (RGPD)
func (h *Handler) RequestDataDeletion(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
var req struct {
Password string `json:"password" binding:"required"`
Reason string `json:"reason"`
}
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request data")
return
}
err := h.service.RequestDataDeletion(userID, req.Password, req.Reason)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.Success(c, nil)
}
// GetAccountStatus récupère le statut du compte
func (h *Handler) GetAccountStatus(c *gin.Context) {
userID, exists := common.GetUserIDFromContext(c)
if !exists {
response.Unauthorized(c, "User ID not found")
return
}
status, err := h.service.GetAccountStatus(userID)
if err != nil {
response.InternalServerError(c, "Failed to get account status")
return
}
response.Success(c, status)
}