mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
dev day #80
This commit is contained in:
+56
-120
@@ -32,15 +32,12 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
|
||||
// Initialize controllers
|
||||
baseController := &controllers.BaseController{DB: db}
|
||||
authController := controllers.NewAuthController(db)
|
||||
facrController := controllers.NewFACRController(db)
|
||||
contactController := controllers.NewContactController(db, emailService)
|
||||
passwordController := controllers.NewPasswordController(db, emailService)
|
||||
aiController := controllers.NewAIController(db)
|
||||
scoreboardController := controllers.NewScoreboardController(db)
|
||||
youtubeController := controllers.NewYouTubeController(db)
|
||||
aboutController := controllers.NewAboutController(db)
|
||||
galleryController := controllers.NewGalleryController(db)
|
||||
umamiController := controllers.NewUmamiController()
|
||||
filesController := &controllers.FilesController{DB: db}
|
||||
notificationsController := controllers.NewNotificationsController(db, emailService)
|
||||
emailController := controllers.NewEmailController(db)
|
||||
@@ -48,15 +45,15 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
|
||||
seoController := controllers.NewSEOController(db)
|
||||
navigationController := controllers.NewNavigationController(db)
|
||||
pollController := controllers.NewPollController(db)
|
||||
sweepstakesController := controllers.NewSweepstakesController(db, emailService)
|
||||
clothingController := controllers.NewClothingController(db)
|
||||
pageElementConfigController := controllers.NewPageElementConfigController(db)
|
||||
imageProcessingController := &controllers.ImageProcessingController{}
|
||||
articleController := controllers.NewArticleController(db)
|
||||
myuibrixController := &controllers.MyUIbrixController{DB: db}
|
||||
editorPreviewController := controllers.NewEditorPreviewController(db)
|
||||
shortLinkController := controllers.NewShortLinkController(db)
|
||||
commentController := controllers.NewCommentController(db)
|
||||
engagementController := controllers.NewEngagementController(db)
|
||||
engagementController := controllers.NewEngagementController(db, emailService)
|
||||
|
||||
// API v1 group
|
||||
{
|
||||
@@ -79,6 +76,8 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
|
||||
// Public page element configurations
|
||||
api.GET("/page-elements", pageElementConfigController.GetPageElementConfigs)
|
||||
|
||||
api.GET("/clothing", clothingController.GetClothing)
|
||||
|
||||
// Public shortlink creation for visitors (same-site only)
|
||||
api.POST("/shortlinks/public", middleware.RateLimit(30, time.Minute), shortLinkController.PublicCreateShortLink)
|
||||
|
||||
@@ -139,11 +138,22 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
|
||||
// CSRF protect state-changing requests when relying on cookies (Bearer tokens are auto-exempt)
|
||||
protected.Use(middleware.CSRFProtection())
|
||||
{
|
||||
// Sweepstakes (protected)
|
||||
protected.POST("/sweepstakes/:id/enter", middleware.RateLimit(30, time.Minute), sweepstakesController.Enter)
|
||||
protected.POST("/sweepstakes/:id/played", sweepstakesController.MarkVisualPlayed)
|
||||
protected.GET("/sweepstakes/my-winnings", sweepstakesController.MyWinnings)
|
||||
// Engagement leaderboard (auth)
|
||||
protected.GET("/engagement/leaderboard", engagementController.GetLeaderboard)
|
||||
// Engagement profile & actions
|
||||
protected.GET("/engagement/profile", engagementController.GetProfile)
|
||||
protected.PATCH("/engagement/profile", engagementController.PatchProfile)
|
||||
protected.PATCH("/engagement/avatar", engagementController.PatchAvatar)
|
||||
protected.POST("/engagement/redeem", engagementController.Redeem)
|
||||
protected.POST("/engagement/redeem", middleware.RateLimit(5, time.Hour), engagementController.Redeem)
|
||||
protected.GET("/engagement/achievements", engagementController.GetAchievements)
|
||||
protected.GET("/engagement/transactions", engagementController.GetMyTransactions)
|
||||
// Engagement new actions
|
||||
protected.POST("/engagement/checkin", middleware.RateLimit(10, time.Minute), engagementController.Checkin)
|
||||
protected.POST("/engagement/article-read", middleware.RateLimit(60, time.Minute), engagementController.ArticleRead)
|
||||
// Comments (create/update/delete)
|
||||
protected.POST("/comments", middleware.RateLimit(20, time.Minute), commentController.CreateComment)
|
||||
protected.PUT("/comments/:id", commentController.UpdateComment)
|
||||
@@ -259,12 +269,14 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
|
||||
admin := protected.Group("/admin")
|
||||
admin.Use(middleware.RoleAuth("admin"))
|
||||
{
|
||||
// Comments moderation
|
||||
// Comments
|
||||
commentsAdmin := admin.Group("/comments")
|
||||
{
|
||||
commentsAdmin.GET("", commentController.AdminList)
|
||||
commentsAdmin.PATCH("/:id/status", commentController.AdminUpdateStatus)
|
||||
commentsAdmin.POST("/ban", commentController.AdminBanUser)
|
||||
commentsAdmin.GET("/bans", commentController.AdminListBans)
|
||||
commentsAdmin.POST("/bans/:id/lift", commentController.AdminLiftBan)
|
||||
commentsAdmin.GET("/unban-requests", commentController.AdminListUnban)
|
||||
commentsAdmin.POST("/unban-requests/:id/resolve", commentController.AdminResolveUnban)
|
||||
}
|
||||
@@ -446,10 +458,10 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
|
||||
{
|
||||
clothing.GET("", clothingController.GetClothingAdmin)
|
||||
clothing.GET("/:id", clothingController.GetClothingByID)
|
||||
clothing.POST("", clothingController.CreateClothing)
|
||||
clothing.PUT("/:id", clothingController.UpdateClothing)
|
||||
clothing.DELETE("/:id", clothingController.DeleteClothing)
|
||||
clothing.POST("/reorder", clothingController.UpdateClothingOrder)
|
||||
clothing.POST("", clothingController.CreateClothing)
|
||||
clothing.PUT("/:id", clothingController.UpdateClothing)
|
||||
clothing.DELETE("/:id", clothingController.DeleteClothing)
|
||||
clothing.POST("/reorder", clothingController.UpdateClothingOrder)
|
||||
}
|
||||
|
||||
// Polls management (admin)
|
||||
@@ -473,6 +485,10 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
|
||||
engagement.DELETE("/rewards/:id", engagementController.AdminDeleteReward)
|
||||
engagement.GET("/redemptions", engagementController.AdminListRedemptions)
|
||||
engagement.PATCH("/redemptions/:id", engagementController.AdminUpdateRedemptionStatus)
|
||||
engagement.GET("/leaderboard", engagementController.AdminGetLeaderboard)
|
||||
engagement.GET("/transactions", engagementController.AdminListTransactions)
|
||||
engagement.POST("/adjust", engagementController.AdminAdjustPoints)
|
||||
engagement.GET("/profile/:user_id", engagementController.AdminGetUserProfile)
|
||||
}
|
||||
|
||||
// Page element configurations management (admin)
|
||||
@@ -501,120 +517,40 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
|
||||
shortlinks.GET("", shortLinkController.ListShortLinks)
|
||||
shortlinks.GET("/:id/stats", shortLinkController.GetShortLinkStats)
|
||||
}
|
||||
|
||||
// Sweepstakes management (admin)
|
||||
sw := admin.Group("/sweepstakes")
|
||||
{
|
||||
sw.GET("", sweepstakesController.AdminList)
|
||||
sw.POST("", sweepstakesController.AdminCreate)
|
||||
sw.PUT("/:id", sweepstakesController.AdminUpdate)
|
||||
sw.DELETE("/:id", sweepstakesController.AdminDelete)
|
||||
sw.GET("/:id/entries", sweepstakesController.AdminEntries)
|
||||
sw.GET("/:id/winners", sweepstakesController.AdminWinners)
|
||||
sw.PATCH("/:id/winners/:winner_id", sweepstakesController.AdminUpdateWinner)
|
||||
sw.PATCH("/:id/winners/:winner_id/prize", sweepstakesController.AdminSetWinnerPrize)
|
||||
sw.GET("/:id/visual", sweepstakesController.AdminVisualData)
|
||||
// Prizes
|
||||
sw.GET("/:id/prizes", sweepstakesController.AdminListPrizes)
|
||||
sw.POST("/:id/prizes", sweepstakesController.AdminCreatePrize)
|
||||
sw.PUT("/:id/prizes/:prize_id", sweepstakesController.AdminUpdatePrize)
|
||||
sw.DELETE("/:id/prizes/:prize_id", sweepstakesController.AdminDeletePrize)
|
||||
sw.POST("/:id/prizes/reorder", sweepstakesController.AdminReorderPrizes)
|
||||
// Finalize (draw winners)
|
||||
sw.POST("/:id/finalize", sweepstakesController.AdminFinalize)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Protected routes end
|
||||
}
|
||||
|
||||
// Register analytics routes (public tracking + admin endpoints)
|
||||
RegisterAnalyticsRoutes(api, db)
|
||||
|
||||
// Umami analytics routes
|
||||
api.GET("/umami/config", umamiController.GetUmamiConfig)
|
||||
// Public setup endpoint (no auth required - called during initial setup)
|
||||
api.POST("/umami/initialize-setup", umamiController.InitializeUmamiSetup)
|
||||
|
||||
umami := api.Group("/admin/umami")
|
||||
umami.Use(middleware.JWTAuth(db))
|
||||
umami.Use(middleware.RoleAuth("admin"))
|
||||
{
|
||||
umami.POST("/initialize", umamiController.InitializeUmami)
|
||||
umami.GET("/stats", umamiController.GetStats)
|
||||
umami.GET("/metrics/:type", umamiController.GetMetrics)
|
||||
umami.GET("/pageviews", umamiController.GetPageviews)
|
||||
}
|
||||
|
||||
// Register contact info routes (public + admin endpoints)
|
||||
RegisterContactInfoRoutes(api, db)
|
||||
|
||||
// Public API routes
|
||||
// Allow uploads publicly so initial setup can upload a club logo before an admin exists.
|
||||
api.POST("/upload", middleware.RateLimit(30, time.Minute), baseController.UploadImage)
|
||||
|
||||
// Image processing endpoints (protected for editors)
|
||||
// Note: Define a dedicated group with required middleware to avoid referencing
|
||||
// the out-of-scope `protected` variable from above.
|
||||
imageProcessing := api.Group("/image-processing")
|
||||
imageProcessing.Use(middleware.JWTAuth(db))
|
||||
imageProcessing.Use(middleware.CSRFProtection())
|
||||
imageProcessing.Use(middleware.RoleAuth("editor"))
|
||||
{
|
||||
imageProcessing.POST("/process", imageProcessingController.ProcessImage)
|
||||
imageProcessing.POST("/crop-upload", imageProcessingController.CropAndUpload)
|
||||
imageProcessing.POST("/quick-edit", imageProcessingController.QuickEdit)
|
||||
}
|
||||
|
||||
// Public scoreboard
|
||||
api.GET("/scoreboard", scoreboardController.GetPublic)
|
||||
api.GET("/scoreboard/colors/derive", scoreboardController.DeriveColors)
|
||||
|
||||
// ... (rest of the code remains the same)
|
||||
api.GET("/settings", baseController.GetPublicSettings)
|
||||
api.GET("/competition-aliases", baseController.GetPublicCompetitionAliases)
|
||||
api.GET("/public/team-logo-overrides", baseController.GetPublicTeamLogoOverrides)
|
||||
|
||||
// Articles (public)
|
||||
api.GET("/articles/featured", baseController.GetFeaturedArticles)
|
||||
api.GET("/articles", baseController.GetArticles)
|
||||
api.GET("/articles/:id", baseController.GetArticle)
|
||||
api.GET("/articles/slug/:slug", baseController.GetArticleBySlug)
|
||||
api.POST("/articles/:id/read", baseController.IncrementArticleRead)
|
||||
api.POST("/articles/:id/track-view", baseController.TrackArticleView)
|
||||
// Public read-only access to article-match link
|
||||
api.GET("/articles/:id/match-link", baseController.GetArticleMatchLink)
|
||||
// Public categories
|
||||
api.GET("/categories", baseController.GetCategories)
|
||||
// Public YouTube cached videos
|
||||
api.GET("/youtube/videos", youtubeController.GetYouTubeVideos)
|
||||
// Public About page
|
||||
api.GET("/about", aboutController.GetPublicAboutPage)
|
||||
api.GET("/teams", baseController.GetTeams)
|
||||
api.GET("/teams/:id", baseController.GetTeam)
|
||||
api.GET("/players", baseController.GetPlayers)
|
||||
api.GET("/players/:id", baseController.GetPlayer)
|
||||
api.GET("/sponsors", baseController.GetSponsors)
|
||||
// Public banners
|
||||
api.GET("/banners", baseController.GetBanners)
|
||||
api.GET("/matches", baseController.GetMatches)
|
||||
api.GET("/matches/history", baseController.GetMatchesHistory)
|
||||
api.GET("/standings", baseController.GetStandings)
|
||||
|
||||
// Gallery (public): albums and photos
|
||||
api.GET("/gallery/albums", galleryController.GetGalleryAlbums) // Get all albums
|
||||
api.GET("/gallery/albums/:id", galleryController.GetGalleryAlbum) // Get single album with photos
|
||||
api.GET("/gallery/proxy-image", galleryController.ProxyImage) // Proxy Zonerama images to avoid CORS
|
||||
|
||||
// Legacy Zonerama endpoints (keep for backwards compatibility)
|
||||
api.GET("/zonerama/album", baseController.GetZoneramaAlbum)
|
||||
// Alias to support hyphenated path used by some frontend calls
|
||||
api.GET("/zonerama-album", baseController.GetZoneramaAlbum)
|
||||
api.GET("/zonerama/picks", baseController.GetZoneramaPicks)
|
||||
|
||||
// Clothing (public) - active items only
|
||||
api.GET("/clothing", clothingController.GetClothing)
|
||||
|
||||
// Polls (public)
|
||||
api.GET("/polls", pollController.GetPolls)
|
||||
api.GET("/polls/:id", pollController.GetPoll)
|
||||
api.POST("/polls/:id/vote", middleware.RateLimit(10, time.Minute), pollController.Vote)
|
||||
api.GET("/polls/:id/results", pollController.GetPollResults)
|
||||
|
||||
// Contact form and newsletter endpoints (public) – rate limited to prevent abuse
|
||||
api.POST("/contact", middleware.RateLimit(10, time.Minute), contactController.SubmitContactForm)
|
||||
api.POST("/newsletter/subscribe", middleware.RateLimit(30, time.Minute), contactController.SubscribeToNewsletter)
|
||||
api.POST("/newsletter/setup", middleware.RateLimit(30, time.Minute), contactController.SetupNewsletterPreferences)
|
||||
api.POST("/newsletter/unsubscribe/:email", middleware.RateLimit(30, time.Minute), contactController.UnsubscribeFromNewsletter)
|
||||
// Token-based management (no auth)
|
||||
api.GET("/newsletter/preferences", contactController.GetNewsletterPreferencesByToken)
|
||||
api.POST("/newsletter/preferences", contactController.SaveNewsletterPreferencesByToken)
|
||||
api.POST("/newsletter/unsubscribe-token", contactController.UnsubscribeByToken)
|
||||
// Public sweepstakes endpoints
|
||||
api.GET("/sweepstakes/current", sweepstakesController.GetCurrent)
|
||||
api.GET("/sweepstakes/:id/visual", sweepstakesController.PublicVisualData)
|
||||
|
||||
}
|
||||
// FACR scraper endpoints (integrated): /api/v1/facr/*
|
||||
facr := api.Group("/facr")
|
||||
{
|
||||
facr.GET("/club/search", facrController.SearchClubs)
|
||||
facr.GET("/club/:type/:id", facrController.GetClubInfo)
|
||||
facr.GET("/club/:type/:id/table", facrController.GetClubTables)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// SetupRootRoutes registers endpoints at the root (no /api prefix)
|
||||
|
||||
Reference in New Issue
Block a user