diff options
Diffstat (limited to 'backend/api')
| -rw-r--r-- | backend/api/rate.go | 20 | ||||
| -rw-r--r-- | backend/api/routes.go | 28 |
2 files changed, 34 insertions, 14 deletions
diff --git a/backend/api/rate.go b/backend/api/rate.go new file mode 100644 index 0000000..1e262af --- /dev/null +++ b/backend/api/rate.go | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | package api | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "net/http" | ||
| 5 | |||
| 6 | "golang.org/x/time/rate" | ||
| 7 | |||
| 8 | "github.com/gin-gonic/gin" | ||
| 9 | ) | ||
| 10 | |||
| 11 | func RateLimit(c *gin.Context) { | ||
| 12 | limiter := rate.NewLimiter(1, 5) // don't know if this is too much or not enough tbh | ||
| 13 | if limiter.Allow() { | ||
| 14 | c.Next() | ||
| 15 | } else { | ||
| 16 | c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{ | ||
| 17 | "error": "Rate limit exceeded", | ||
| 18 | }) | ||
| 19 | } | ||
| 20 | } | ||
diff --git a/backend/api/routes.go b/backend/api/routes.go index ecfb54b..c3124f9 100644 --- a/backend/api/routes.go +++ b/backend/api/routes.go | |||
| @@ -18,29 +18,29 @@ func InitRoutes(router *gin.Engine) { | |||
| 18 | c.File("docs/index.html") | 18 | c.File("docs/index.html") |
| 19 | }) | 19 | }) |
| 20 | // Tokens, login | 20 | // Tokens, login |
| 21 | v1.GET("/token", handlers.GetCookie) | 21 | v1.GET("/token", RateLimit, handlers.GetCookie) |
| 22 | v1.DELETE("/token", handlers.DeleteCookie) | 22 | v1.DELETE("/token", RateLimit, handlers.DeleteCookie) |
| 23 | v1.GET("/login", handlers.Login) | 23 | v1.GET("/login", RateLimit, handlers.Login) |
| 24 | // Users, profiles | 24 | // Users, profiles |
| 25 | v1.GET("/profile", IsAuthenticated, handlers.Profile) | 25 | v1.GET("/profile", RateLimit, IsAuthenticated, handlers.Profile) |
| 26 | v1.PUT("/profile", IsAuthenticated, handlers.UpdateCountryCode) | 26 | v1.PUT("/profile", IsAuthenticated, handlers.UpdateCountryCode) |
| 27 | v1.POST("/profile", IsAuthenticated, handlers.UpdateUser) | 27 | v1.POST("/profile", IsAuthenticated, handlers.UpdateUser) |
| 28 | v1.GET("/users/:userid", IsAuthenticated, handlers.FetchUser) | 28 | v1.GET("/users/:userid", IsAuthenticated, handlers.FetchUser) |
| 29 | // Maps | 29 | // Maps |
| 30 | // - Summary | 30 | // - Summary |
| 31 | v1.GET("/maps/:mapid/summary", handlers.FetchMapSummary) | 31 | v1.GET("/maps/:mapid/summary", RateLimit, handlers.FetchMapSummary) |
| 32 | v1.POST("/maps/:mapid/summary", IsAuthenticated, handlers.CreateMapSummary) | 32 | v1.POST("/maps/:mapid/summary", IsAuthenticated, handlers.CreateMapSummary) |
| 33 | v1.PUT("/maps/:mapid/summary", IsAuthenticated, handlers.EditMapSummary) | 33 | v1.PUT("/maps/:mapid/summary", IsAuthenticated, handlers.EditMapSummary) |
| 34 | v1.DELETE("/maps/:mapid/summary", IsAuthenticated, handlers.DeleteMapSummary) | 34 | v1.DELETE("/maps/:mapid/summary", IsAuthenticated, handlers.DeleteMapSummary) |
| 35 | v1.PUT("/maps/:mapid/image", IsAuthenticated, handlers.EditMapImage) | 35 | v1.PUT("/maps/:mapid/image", IsAuthenticated, handlers.EditMapImage) |
| 36 | // - Leaderboards | 36 | // - Leaderboards |
| 37 | v1.GET("/maps/:mapid/leaderboards", handlers.FetchMapLeaderboards) | 37 | v1.GET("/maps/:mapid/leaderboards", RateLimit, handlers.FetchMapLeaderboards) |
| 38 | v1.POST("/maps/:mapid/record", IsAuthenticated, handlers.CreateRecordWithDemo) | 38 | v1.POST("/maps/:mapid/record", IsAuthenticated, handlers.CreateRecordWithDemo) |
| 39 | v1.DELETE("/maps/:mapid/record/:recordid", IsAuthenticated, handlers.DeleteRecord) | 39 | v1.DELETE("/maps/:mapid/record/:recordid", IsAuthenticated, handlers.DeleteRecord) |
| 40 | v1.GET("/demos", handlers.DownloadDemoWithID) | 40 | v1.GET("/demos", RateLimit, handlers.DownloadDemoWithID) |
| 41 | // - Discussions | 41 | // - Discussions |
| 42 | v1.GET("/maps/:mapid/discussions", handlers.FetchMapDiscussions) | 42 | v1.GET("/maps/:mapid/discussions", RateLimit, handlers.FetchMapDiscussions) |
| 43 | v1.GET("/maps/:mapid/discussions/:discussionid", handlers.FetchMapDiscussion) | 43 | v1.GET("/maps/:mapid/discussions/:discussionid", RateLimit, handlers.FetchMapDiscussion) |
| 44 | v1.POST("/maps/:mapid/discussions", IsAuthenticated, handlers.CreateMapDiscussion) | 44 | v1.POST("/maps/:mapid/discussions", IsAuthenticated, handlers.CreateMapDiscussion) |
| 45 | v1.POST("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.CreateMapDiscussionComment) | 45 | v1.POST("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.CreateMapDiscussionComment) |
| 46 | v1.PUT("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.EditMapDiscussion) | 46 | v1.PUT("/maps/:mapid/discussions/:discussionid", IsAuthenticated, handlers.EditMapDiscussion) |
| @@ -50,12 +50,12 @@ func InitRoutes(router *gin.Engine) { | |||
| 50 | v1.GET("/rankings/steam", handlers.RankingsSteam) | 50 | v1.GET("/rankings/steam", handlers.RankingsSteam) |
| 51 | v1.GET("/search", handlers.SearchWithQuery) | 51 | v1.GET("/search", handlers.SearchWithQuery) |
| 52 | // Games, chapters, maps | 52 | // Games, chapters, maps |
| 53 | v1.GET("/games", handlers.FetchGames) | 53 | v1.GET("/games", RateLimit, handlers.FetchGames) |
| 54 | v1.GET("/games/:gameid", handlers.FetchChapters) | 54 | v1.GET("/games/:gameid", RateLimit, handlers.FetchChapters) |
| 55 | v1.GET("/chapters/:chapterid", handlers.FetchChapterMaps) | 55 | v1.GET("/chapters/:chapterid", RateLimit, handlers.FetchChapterMaps) |
| 56 | v1.GET("/games/:gameid/maps", handlers.FetchMaps) | 56 | v1.GET("/games/:gameid/maps", RateLimit, handlers.FetchMaps) |
| 57 | // Logs | 57 | // Logs |
| 58 | v1.GET("/logs/score", handlers.ScoreLogs) | 58 | v1.GET("/logs/score", RateLimit, handlers.ScoreLogs) |
| 59 | // v1.GET("/logs/mod", IsAuthenticated, handlers.ModLogs) | 59 | // v1.GET("/logs/mod", IsAuthenticated, handlers.ModLogs) |
| 60 | } | 60 | } |
| 61 | } | 61 | } |