mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-09-25 11:52:03 +00:00
feat: implement rate limiting for public widget endpoints with Redis support
This commit is contained in:
+6
-6
@@ -227,12 +227,12 @@ func initHandlers(g *fastglue.Fastglue, hub *ws.Hub) {
|
||||
// Widget APIs.
|
||||
g.GET("/api/v1/widget/chat/settings/launcher", handleGetChatLauncherSettings)
|
||||
g.GET("/api/v1/widget/chat/settings", handleGetChatSettings)
|
||||
g.POST("/api/v1/widget/chat/conversations/init", widgetAuth(handleChatInit))
|
||||
g.POST("/api/v1/widget/chat/conversations", widgetAuth(handleGetConversations))
|
||||
g.POST("/api/v1/widget/chat/conversations/{uuid}/update-last-seen", widgetAuth(handleChatUpdateLastSeen))
|
||||
g.POST("/api/v1/widget/chat/conversations/{uuid}", widgetAuth(handleChatGetConversation))
|
||||
g.POST("/api/v1/widget/chat/conversations/{uuid}/message", widgetAuth(handleChatSendMessage))
|
||||
g.POST("/api/v1/widget/media/upload", widgetAuth(handleWidgetMediaUpload))
|
||||
g.POST("/api/v1/widget/chat/conversations/init", rateLimitWidget(widgetAuth(handleChatInit)))
|
||||
g.POST("/api/v1/widget/chat/conversations", rateLimitWidget(widgetAuth(handleGetConversations)))
|
||||
g.POST("/api/v1/widget/chat/conversations/{uuid}/update-last-seen", rateLimitWidget(widgetAuth(handleChatUpdateLastSeen)))
|
||||
g.POST("/api/v1/widget/chat/conversations/{uuid}", rateLimitWidget(widgetAuth(handleChatGetConversation)))
|
||||
g.POST("/api/v1/widget/chat/conversations/{uuid}/message", rateLimitWidget(widgetAuth(handleChatSendMessage)))
|
||||
g.POST("/api/v1/widget/media/upload", rateLimitWidget(widgetAuth(handleWidgetMediaUpload)))
|
||||
|
||||
// Frontend pages.
|
||||
g.GET("/", notAuthPage(serveIndexPage))
|
||||
|
||||
+10
@@ -36,6 +36,7 @@ import (
|
||||
notifier "github.com/abhinavxd/libredesk/internal/notification"
|
||||
emailnotifier "github.com/abhinavxd/libredesk/internal/notification/providers/email"
|
||||
"github.com/abhinavxd/libredesk/internal/oidc"
|
||||
"github.com/abhinavxd/libredesk/internal/ratelimit"
|
||||
"github.com/abhinavxd/libredesk/internal/report"
|
||||
"github.com/abhinavxd/libredesk/internal/role"
|
||||
"github.com/abhinavxd/libredesk/internal/search"
|
||||
@@ -927,3 +928,12 @@ func getLogLevel(lvl string) logf.Level {
|
||||
return logf.InfoLevel
|
||||
}
|
||||
}
|
||||
|
||||
// initRateLimit initializes the rate limiter.
|
||||
func initRateLimit(redisClient *redis.Client) *ratelimit.Limiter {
|
||||
var config ratelimit.Config
|
||||
if err := ko.UnmarshalWithConf("rate_limit", &config, koanf.UnmarshalConf{Tag: "toml"}); err != nil {
|
||||
log.Fatalf("error unmarshalling rate limit config: %v", err)
|
||||
}
|
||||
return ratelimit.New(redisClient, config)
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/abhinavxd/libredesk/internal/inbox"
|
||||
"github.com/abhinavxd/libredesk/internal/media"
|
||||
"github.com/abhinavxd/libredesk/internal/oidc"
|
||||
"github.com/abhinavxd/libredesk/internal/ratelimit"
|
||||
"github.com/abhinavxd/libredesk/internal/role"
|
||||
"github.com/abhinavxd/libredesk/internal/setting"
|
||||
"github.com/abhinavxd/libredesk/internal/tag"
|
||||
@@ -95,6 +96,7 @@ type App struct {
|
||||
customAttribute *customAttribute.Manager
|
||||
report *report.Manager
|
||||
webhook *webhook.Manager
|
||||
rateLimit *ratelimit.Limiter
|
||||
|
||||
// Global state that stores data on an available app update.
|
||||
update *AppUpdate
|
||||
@@ -202,6 +204,7 @@ func main() {
|
||||
sla = initSLA(db, team, settings, businessHours, notifier, template, user, i18n)
|
||||
conversation = initConversations(i18n, sla, status, priority, wsHub, notifier, db, inbox, user, team, media, settings, csat, automation, template, webhook)
|
||||
autoassigner = initAutoAssigner(team, user, conversation)
|
||||
rateLimiter = initRateLimit(rdb)
|
||||
)
|
||||
|
||||
wsHub.SetConversationStore(conversation)
|
||||
@@ -253,6 +256,7 @@ func main() {
|
||||
macro: initMacro(db, i18n),
|
||||
ai: initAI(db, i18n),
|
||||
webhook: webhook,
|
||||
rateLimit: rateLimiter,
|
||||
}
|
||||
app.consts.Store(constants)
|
||||
|
||||
|
||||
@@ -154,3 +154,14 @@ func getWidgetClaimsOptional(r *fastglue.Request) *Claims {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// rateLimitWidget applies rate limiting to widget endpoints.
|
||||
func rateLimitWidget(handler fastglue.FastRequestHandler) fastglue.FastRequestHandler {
|
||||
return func(r *fastglue.Request) error {
|
||||
app := r.Context.(*App)
|
||||
if err := app.rateLimit.CheckWidgetLimit(r.RequestCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
return handler(r)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user