package api import ( "net/http" "strconv" "time" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/redis/go-redis/v9" "go.uber.org/zap" trackcore "veza-backend-api/internal/core/track" "veza-backend-api/internal/handlers" "veza-backend-api/internal/repositories" "veza-backend-api/internal/services" ) // setupUserRoutes configure les routes utilisateur func (r *APIRouter) setupUserRoutes(router *gin.RouterGroup) { userRepo := repositories.NewGormUserRepository(r.db.GormDB) userService := services.NewUserServiceWithDB(userRepo, r.db.GormDB) profileHandler := handlers.NewProfileHandler(userService, r.logger) if r.config != nil && r.config.PermissionService != nil { profileHandler.SetPermissionService(r.config.PermissionService) } socialService := services.NewSocialService(r.db, r.logger) profileHandler.SetSocialService(socialService) if r.notificationService == nil { r.notificationService = services.NewNotificationService(r.db, r.logger) if r.pushService != nil { r.notificationService.SetPushService(r.pushService) } } profileHandler.SetNotificationService(r.notificationService) users := router.Group("/users") { users.GET("", profileHandler.ListUsers) users.GET("/:id", profileHandler.GetProfile) users.GET("/by-username/:username", profileHandler.GetProfileByUsername) users.GET("/search", profileHandler.SearchUsers) if r.config.AuthMiddleware != nil { protected := users.Group("") protected.Use(r.config.AuthMiddleware.RequireAuth()) r.applyCSRFProtection(protected) settingsHandler := handlers.NewSettingsHandler(userService, r.logger) protected.GET("/settings", settingsHandler.GetSettings) protected.PUT("/settings", settingsHandler.UpdateSettings) userOwnerResolver := func(c *gin.Context) (uuid.UUID, error) { userIDStr := c.Param("id") return uuid.Parse(userIDStr) } protected.PUT("/:id", r.config.AuthMiddleware.RequireOwnershipOrAdmin("user", userOwnerResolver), profileHandler.UpdateProfile) protected.DELETE("/:id", r.config.AuthMiddleware.RequireOwnershipOrAdmin("user", userOwnerResolver), profileHandler.DeleteUser) protected.GET("/:id/completion", profileHandler.GetProfileCompletion) presenceService := services.NewPresenceService(r.db.GormDB, r.logger) presenceHandler := handlers.NewPresenceHandler(presenceService, r.logger) protected.PUT("/me/presence", presenceHandler.UpdatePresence) protected.GET("/:id/presence", presenceHandler.GetPresence) protected.POST("/:id/follow", profileHandler.FollowUser) protected.DELETE("/:id/follow", profileHandler.UnfollowUser) protected.POST("/:id/block", profileHandler.BlockUser) protected.DELETE("/:id/block", profileHandler.UnblockUser) roleService := services.NewRoleService(r.db.GormDB) roleHandler := handlers.NewRoleHandler(roleService, r.logger) protected.POST("/:id/roles", roleHandler.AssignRole) protected.DELETE("/:id/roles/:roleId", roleHandler.RevokeRole) avatarUploadDir := r.config.UploadDir if avatarUploadDir == "" { avatarUploadDir = "uploads/avatars" } imageService := services.NewImageService(avatarUploadDir) avatarHandler := handlers.NewAvatarHandler(imageService, userService) protected.POST("/:id/avatar", avatarHandler.UploadAvatar) protected.DELETE("/:id/avatar", avatarHandler.DeleteAvatar) uploadDir := r.config.UploadDir if uploadDir == "" { uploadDir = "uploads/tracks" } likeService := services.NewTrackLikeService(r.db.GormDB, r.logger) trackService := trackcore.NewTrackServiceWithDB(r.db, r.logger, uploadDir) if r.config.CacheService != nil { trackService.SetCacheService(r.config.CacheService) } streamService := services.NewStreamServiceWithAPIKey(r.config.StreamServerURL, r.config.StreamServerInternalAPIKey, r.logger) trackService.SetStreamService(streamService) // INT-02: Enable HLS pipeline for regular uploads trackUploadService := services.NewTrackUploadService(r.db.GormDB, r.logger) var redisClient *redis.Client if r.config != nil { redisClient = r.config.RedisClient } chunksDir := uploadDir + "/chunks" chunkService := services.NewTrackChunkService(chunksDir, redisClient, r.logger) trackHandlerForLikes := trackcore.NewTrackHandler( trackService, trackUploadService, chunkService, likeService, streamService, ) protected.GET("/:id/likes", trackHandlerForLikes.GetUserLikedTracks) dataExportService := services.NewDataExportService(r.db.GormDB, r.logger) exportHandler := func(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "User ID not found"}) return } userUUID, ok := userID.(uuid.UUID) if !ok { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) return } jsonData, err := dataExportService.ExportUserDataAsJSON(c.Request.Context(), userUUID) if err != nil { r.logger.Error("Failed to export user data", zap.Error(err), zap.String("user_id", userUUID.String())) c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to export user data"}) return } filename := "veza-data-export-" + time.Now().Format("2006-01-02T15-04-05") + ".json" c.Header("Content-Type", "application/json") c.Header("Content-Disposition", `attachment; filename="`+filename+`"`) c.Header("Content-Length", strconv.Itoa(len(jsonData))) c.Data(http.StatusOK, "application/json", jsonData) } protected.GET("/me/export", exportHandler) } } } // setupRoleRoutes configure les routes de gestion des rĂ´les func (r *APIRouter) setupRoleRoutes(router *gin.RouterGroup) { roleService := services.NewRoleService(r.db.GormDB) roleHandler := handlers.NewRoleHandler(roleService, r.logger) roles := router.Group("/roles") { if r.config.AuthMiddleware != nil { protected := roles.Group("") protected.Use(r.config.AuthMiddleware.RequireAuth()) r.applyCSRFProtection(protected) { protected.GET("", roleHandler.GetRoles) protected.GET("/:id", roleHandler.GetRole) protected.POST("", roleHandler.CreateRole) protected.PUT("/:id", roleHandler.UpdateRole) protected.DELETE("/:id", roleHandler.DeleteRole) } } } }