From 535e96b4917209ff437cc1c2d90355b6af29059c Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Fri, 29 Mar 2024 22:59:13 -0700 Subject: [PATCH] Rate limit the user Mark Explicit endpoint --- pkg/config/config.go | 7 +++++++ pkg/controller/api/mark_explicit.go | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pkg/config/config.go b/pkg/config/config.go index 15833fa..7bf1235 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -66,6 +66,13 @@ const ( ContactRateLimitCooldownAt = 1 ContactRateLimitCooldown = 2 * time.Minute + // "Mark Explicit" rate limit to curb a mischievous user just bulk marking the + // whole gallery as explicit. + MarkExplicitRateLimitWindow = 1 * time.Hour + MarkExplicitRateLimit = 20 // 10 failed MarkExplicit attempts = locked for full hour + MarkExplicitRateLimitCooldownAt = 10 // 10 photos in an hour, start throttling. + MarkExplicitRateLimitCooldown = time.Minute + // How frequently to refresh LastLoginAt since sessions are long-lived. LastLoginAtCooldown = time.Hour diff --git a/pkg/controller/api/mark_explicit.go b/pkg/controller/api/mark_explicit.go index 21a0ee5..ca9f819 100644 --- a/pkg/controller/api/mark_explicit.go +++ b/pkg/controller/api/mark_explicit.go @@ -4,8 +4,10 @@ import ( "fmt" "net/http" + "code.nonshy.com/nonshy/website/pkg/config" "code.nonshy.com/nonshy/website/pkg/log" "code.nonshy.com/nonshy/website/pkg/models" + "code.nonshy.com/nonshy/website/pkg/ratelimit" "code.nonshy.com/nonshy/website/pkg/session" "code.nonshy.com/nonshy/website/pkg/templates" ) @@ -61,6 +63,25 @@ func MarkPhotoExplicit() http.HandlerFunc { } if !photo.Explicit { + // Rate limit how frequently they are tagging photos, in case a user is just going around + // and tagging EVERYTHING. + if !currentUser.IsAdmin { + limiter := &ratelimit.Limiter{ + Namespace: "mark_explicit", + ID: currentUser.ID, + Limit: config.MarkExplicitRateLimit, + Window: config.MarkExplicitRateLimitWindow, + CooldownAt: config.MarkExplicitRateLimitCooldownAt, + Cooldown: config.MarkExplicitRateLimitCooldown, + } + if err := limiter.Ping(); err != nil { + SendJSON(w, http.StatusTooManyRequests, Response{ + Error: "We appreciate the enthusiasm, but you seem to be marking an unusually high number of photos!\n\n" + err.Error(), + }) + return + } + } + photo.Explicit = true if err := photo.Save(); err != nil { SendJSON(w, http.StatusBadRequest, Response{