This commit is contained in:
Tomas Dvorak
2025-11-02 01:04:02 +01:00
parent ac886502e0
commit b9cea0cd77
153 changed files with 43713 additions and 1700 deletions
+77 -3
View File
@@ -53,13 +53,19 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.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)
// API v1 group
{
// Health check
api.GET("/health", baseController.HealthCheck)
// CSRF token for cookie-based clients
api.GET("/csrf-token", middleware.GetCSRFToken)
// Image proxy (public) to work around CORS when reading images in Canvas on the frontend
api.GET("/proxy/image", baseController.ProxyImage)
@@ -73,6 +79,9 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
// Public page element configurations
api.GET("/page-elements", pageElementConfigController.GetPageElementConfigs)
// Public shortlink creation for visitors (same-site only)
api.POST("/shortlinks/public", middleware.RateLimit(30, time.Minute), shortLinkController.PublicCreateShortLink)
// Email tracking (public)
api.GET("/email/open.gif", emailController.OpenPixel)
api.GET("/email/click", emailController.ClickRedirect)
@@ -118,10 +127,47 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
events.GET("/:id", eventController.GetEventByID)
}
// Comments (public list)
api.GET("/comments", commentController.GetComments)
// Engagement (public + protected)
api.GET("/engagement/rewards", engagementController.GetRewards)
// Protected routes (require authentication)
protected := api.Group("")
protected.Use(middleware.JWTAuth(db))
// CSRF protect state-changing requests when relying on cookies (Bearer tokens are auto-exempt)
protected.Use(middleware.CSRFProtection())
{
// Engagement profile & actions
protected.GET("/engagement/profile", engagementController.GetProfile)
protected.PATCH("/engagement/avatar", engagementController.PatchAvatar)
protected.POST("/engagement/redeem", engagementController.Redeem)
protected.GET("/engagement/achievements", engagementController.GetAchievements)
// Comments (create/update/delete)
protected.POST("/comments", middleware.RateLimit(20, time.Minute), commentController.CreateComment)
protected.PUT("/comments/:id", commentController.UpdateComment)
protected.DELETE("/comments/:id", commentController.DeleteComment)
// Comment reactions and unban request
protected.POST("/comments/:id/react", middleware.RateLimit(60, time.Minute), commentController.React)
protected.DELETE("/comments/:id/react", commentController.Unreact)
protected.POST("/comments/unban-request", middleware.RateLimit(5, time.Hour), commentController.CreateUnbanRequest)
protected.POST("/comments/:id/report", middleware.RateLimit(10, time.Hour), commentController.ReportComment)
// Editor preview endpoints (authenticated editors)
editor := protected.Group("/editor")
editor.Use(middleware.RoleAuth("editor"))
{
// Real-time preview state
editor.GET("/preview/:session_id", editorPreviewController.GetPreviewState)
editor.POST("/preview/:session_id", editorPreviewController.UpdatePreviewState)
editor.POST("/preview/:session_id/apply", editorPreviewController.ApplyPreviewChanges)
editor.DELETE("/preview/:session_id", editorPreviewController.DiscardPreviewChanges)
// Validation and variants
editor.POST("/preview/validate", editorPreviewController.ValidatePreviewConfig)
editor.GET("/variants/:element_name", editorPreviewController.GetAvailableVariants)
}
// Newsletter preferences token for current user
protected.GET("/newsletter/token/me", contactController.GetNewsletterTokenForUser)
@@ -134,6 +180,7 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
ai.POST("/blog/generate", aiController.GenerateBlog)
ai.POST("/about/generate", aiController.GenerateAboutPage)
ai.POST("/css/generate", aiController.GenerateCSS)
ai.POST("/instagram/generate", aiController.GenerateInstagram)
}
// User profile
@@ -212,6 +259,15 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
admin := protected.Group("/admin")
admin.Use(middleware.RoleAuth("admin"))
{
// Comments moderation
commentsAdmin := admin.Group("/comments")
{
commentsAdmin.GET("", commentController.AdminList)
commentsAdmin.PATCH("/:id/status", commentController.AdminUpdateStatus)
commentsAdmin.POST("/ban", commentController.AdminBanUser)
commentsAdmin.GET("/unban-requests", commentController.AdminListUnban)
commentsAdmin.POST("/unban-requests/:id/resolve", commentController.AdminResolveUnban)
}
// Admin-only endpoints for managing sponsors, etc. (user CRUD removed; no handlers defined)
// Competition aliases (admin)
@@ -357,6 +413,7 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
files.GET("", filesController.GetAllFiles)
files.GET("/unused", filesController.GetUnusedFiles)
files.GET("/duplicates", filesController.GetDuplicateFiles)
files.GET("/usage", filesController.GetStorageUsage)
files.GET("/:id/usages", filesController.GetFileUsages)
files.DELETE("/:id", filesController.DeleteFile)
files.POST("/scan", filesController.ScanAndSyncFiles)
@@ -404,6 +461,18 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
polls.PUT("/:id", pollController.UpdatePoll)
polls.DELETE("/:id", pollController.DeletePoll)
polls.GET("/:id/stats", pollController.GetPollStats)
polls.GET("/:id/votes", pollController.AdminListVotes)
}
// Engagement management (admin)
engagement := admin.Group("/engagement")
{
engagement.GET("/rewards", engagementController.AdminListRewards)
engagement.POST("/rewards", engagementController.AdminCreateReward)
engagement.PUT("/rewards/:id", engagementController.AdminUpdateReward)
engagement.DELETE("/rewards/:id", engagementController.AdminDeleteReward)
engagement.GET("/redemptions", engagementController.AdminListRedemptions)
engagement.PATCH("/redemptions/:id", engagementController.AdminUpdateRedemptionStatus)
}
// Page element configurations management (admin)
@@ -460,8 +529,13 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
// 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)
imageProcessing := protected.Group("/image-processing")
// 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)
@@ -472,7 +546,7 @@ func SetupRoutes(api *gin.RouterGroup, db *gorm.DB) {
api.GET("/scoreboard", scoreboardController.GetPublic)
api.GET("/scoreboard/colors/derive", scoreboardController.DeriveColors)
// Public core endpoints
// ... (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)