Merge pull request 'feature/ratelimitter' (#9) from feature/ratelimitter into dev
Reviewed-on: winter-access/backend_nam#9
This commit is contained in:
commit
94101e9ba4
|
|
@ -19,6 +19,7 @@ type BackboneController struct {
|
|||
func (bc *BackboneController) Route() {
|
||||
rg := bc.rg.Group("/backbone")
|
||||
rg.Use(middleware.AuthMiddleware())
|
||||
rg.Use(middleware.RateLimitMiddleware())
|
||||
{
|
||||
rg.GET("", bc.GetBackbone())
|
||||
rg.POST("", bc.CreateBackbone())
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type DevicePortController struct {
|
|||
func (dc *DevicePortController) Route() {
|
||||
rg := dc.rg.Group("/device-port")
|
||||
rg.Use(middleware.AuthMiddleware())
|
||||
rg.Use(middleware.RateLimitMiddleware())
|
||||
{
|
||||
rg.GET("", dc.GetDevicePort())
|
||||
rg.POST("", dc.CreateDevicePort())
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type DeviceController struct {
|
|||
func (dc *DeviceController) Route() {
|
||||
rg := dc.rg.Group("/devices")
|
||||
rg.Use(middleware.AuthMiddleware())
|
||||
rg.Use(middleware.RateLimitMiddleware())
|
||||
{
|
||||
rg.POST("", dc.CreateDevice())
|
||||
rg.GET("", dc.GetAllDevices())
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type FishboneController struct {
|
|||
func (fc *FishboneController) Route() {
|
||||
rg := fc.rg.Group("/fishbone")
|
||||
rg.Use(middleware.AuthMiddleware())
|
||||
rg.Use(middleware.RateLimitMiddleware())
|
||||
{
|
||||
rg.GET("", fc.GetFishbone())
|
||||
rg.POST("", fc.CreateFishbone())
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type TowerController struct {
|
|||
func (tc *TowerController) Route() {
|
||||
rg := tc.rg.Group("/tower")
|
||||
rg.Use(middleware.AuthMiddleware())
|
||||
rg.Use(middleware.RateLimitMiddleware())
|
||||
{
|
||||
rg.GET("", tc.GetTower())
|
||||
rg.POST("", tc.CreateTower())
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package controller
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"users_management/m/middleware"
|
||||
"users_management/m/model/dto"
|
||||
"users_management/m/usecase"
|
||||
"users_management/m/utils/common"
|
||||
|
|
@ -17,7 +18,10 @@ type UsersController struct {
|
|||
|
||||
func (uc *UsersController) Route() {
|
||||
rg:= uc.rg.Group("/users")
|
||||
rg.Use(middleware.RateLoginMiddleware())
|
||||
{
|
||||
rg.POST("/login", uc.Login())
|
||||
}
|
||||
rg.POST("/logout", uc.Logout())
|
||||
}
|
||||
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -44,6 +44,7 @@ require (
|
|||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/time v0.10.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -101,6 +101,8 @@ golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
|||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
|
||||
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"users_management/m/model/dto/res"
|
||||
"users_management/m/utils/common"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
|
@ -50,6 +52,15 @@ func AuthMiddleware() gin.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
var authResponse res.AuthMeResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&authResponse); err != nil {
|
||||
common.ErrorResponses(c, http.StatusInternalServerError, err.Error())
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.Set("userID", authResponse.Data.NomorInduk)
|
||||
|
||||
c.Next()
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
"users_management/m/utils/common"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
var (
|
||||
rateLimiters = make(map[string]*rate.Limiter)
|
||||
mu sync.Mutex
|
||||
)
|
||||
|
||||
func getRateLimiter(userID string) *rate.Limiter {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
limiter, exists := rateLimiters[userID]
|
||||
if !exists {
|
||||
limiter = rate.NewLimiter(rate.Every(1*time.Minute), 50) // 1 request per second with a burst of 2 requests
|
||||
rateLimiters[userID] = limiter
|
||||
}
|
||||
|
||||
return limiter
|
||||
}
|
||||
|
||||
func getLoginLimiter() *rate.Limiter {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
limiter, exists := rateLimiters["login"]
|
||||
if !exists {
|
||||
limiter = rate.NewLimiter(rate.Every(1*time.Minute), 4) // 5 request per second with a burst of 10 requests
|
||||
rateLimiters["login"] = limiter
|
||||
}
|
||||
|
||||
return limiter
|
||||
}
|
||||
|
||||
func RateLimitMiddleware() gin.HandlerFunc{
|
||||
return func(c *gin.Context) {
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
common.ErrorResponses(c, http.StatusUnauthorized, "Unauthorized: No user ID found")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
limiter := getRateLimiter(userID.(string))
|
||||
|
||||
if !limiter.Allow() {
|
||||
common.ErrorResponses(c, http.StatusTooManyRequests, "Too many requests")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func RateLoginMiddleware() gin.HandlerFunc{
|
||||
return func(c *gin.Context) {
|
||||
limiter := getLoginLimiter()
|
||||
|
||||
if !limiter.Allow() {
|
||||
common.ErrorResponses(c, http.StatusTooManyRequests, "Too many requests")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue