diff options
| author | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2024-10-31 22:37:31 +0300 |
|---|---|---|
| committer | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2024-10-31 22:37:31 +0300 |
| commit | d7da8f133146de4fba1db13bfbc63242c917f817 (patch) | |
| tree | 319e5216b05e279149e26c3b5cb50e6c88773e27 /backend | |
| parent | backend: better auth check, audit logging (diff) | |
| download | lphub-d7da8f133146de4fba1db13bfbc63242c917f817.tar.gz lphub-d7da8f133146de4fba1db13bfbc63242c917f817.tar.bz2 lphub-d7da8f133146de4fba1db13bfbc63242c917f817.zip | |
backend: add rate limiting
Diffstat (limited to '')
| -rw-r--r-- | backend/api/rate.go | 20 | ||||
| -rw-r--r-- | backend/api/routes.go | 28 | ||||
| -rw-r--r-- | backend/go.mod | 1 | ||||
| -rw-r--r-- | backend/go.sum | 2 |
4 files changed, 37 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 | } |
diff --git a/backend/go.mod b/backend/go.mod index f6eef48..17308f3 100644 --- a/backend/go.mod +++ b/backend/go.mod | |||
| @@ -14,6 +14,7 @@ require ( | |||
| 14 | github.com/swaggo/files v1.0.1 | 14 | github.com/swaggo/files v1.0.1 |
| 15 | github.com/swaggo/gin-swagger v1.6.0 | 15 | github.com/swaggo/gin-swagger v1.6.0 |
| 16 | github.com/swaggo/swag v1.16.3 | 16 | github.com/swaggo/swag v1.16.3 |
| 17 | golang.org/x/time v0.6.0 | ||
| 17 | ) | 18 | ) |
| 18 | 19 | ||
| 19 | require ( | 20 | require ( |
diff --git a/backend/go.sum b/backend/go.sum index 10504e4..647f6f9 100644 --- a/backend/go.sum +++ b/backend/go.sum | |||
| @@ -219,6 +219,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | |||
| 219 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | 219 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= |
| 220 | golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= | 220 | golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= |
| 221 | golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= | 221 | golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= |
| 222 | golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= | ||
| 223 | golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= | ||
| 222 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | 224 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
| 223 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | 225 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
| 224 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | 226 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= |