Skip to content

Commit

Permalink
Add throttling based on URL
Browse files Browse the repository at this point in the history
Do not consider user or user-agent or headers
  • Loading branch information
FrankApiyo committed Aug 22, 2024
1 parent 4bb2c1d commit 830c0ba
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
37 changes: 35 additions & 2 deletions onadata/libs/tests/test_throttle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,43 @@

from rest_framework.test import APIRequestFactory

from onadata.libs.throttle import RequestHeaderThrottle
from onadata.libs.throttle import RequestHeaderThrottle, URLThrottle


class ThrottlingTests(TestCase):
class URLThrottleTests(TestCase):
"""
Test Renderer class.
"""

def setUp(self):
"""
Reset the cache so that no throttles will be active
"""
cache.clear()
self.factory = APIRequestFactory()
self.throttle = URLThrottle()

def test_requests_are_not_throttled_for_get(self):
request = self.factory.get("/bob/submission")
key = self.throttle.get_cache_key(request, None)
self.assertEqual(key, None)

def test_requests_are_not_throttled_for_non_submission_urls(self):
request = self.factory.post("/projects/")
key = self.throttle.get_cache_key(request, None)
self.assertEqual(key, None)

def test_requests_are_throttled(self):
request = self.factory.post("/bob/submission")
key = self.throttle.get_cache_key(request, None)
self.assertEqual(key, 'throttle_method_POST_path_/bob/submission')

request = self.factory.post("/project/124/submission")
key = self.throttle.get_cache_key(request, None)
self.assertEqual(key, 'throttle_method_POST_path_/project/124/submission')


class RequestHeaderThrottlingTests(TestCase):
"""
Test Renderer class.
"""
Expand Down
32 changes: 32 additions & 0 deletions onadata/libs/throttle.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,38 @@
from rest_framework.throttling import SimpleRateThrottle


class URLThrottle(SimpleRateThrottle):

@property
def rate(self):
return getattr(
settings,
"THROTTLE_USERS_RATE",
"300/min"
)

@property
def throttled_users(self):
return getattr(
settings,
"THROTTLE_USERS",
[],
)

def get_form_owner_or_project_from_url(self, url):
path_segments = url.split("/")
if len(path_segments) > 1:
return path_segments[-2]
return None

def get_cache_key(self, request, _):
form_owner_or_project = self.get_form_owner_or_project_from_url(request.path)
if form_owner_or_project in self.throttled_users \
and request.method == 'POST' and '/submission' in request.path:
return f"throttle_method_{request.method}_path_{request.path}"
return None


class RequestHeaderThrottle(SimpleRateThrottle):
"""
Custom Throttling class that throttles requests that match a specific
Expand Down
2 changes: 2 additions & 0 deletions onadata/settings/github_actions_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,5 @@
ODK_TOKEN_FERNET_KEY = "ROsB4T8s1rCJskAdgpTQEKfH2x2K_EX_YBi3UFyoYng=" # nosec
OPENID_CONNECT_PROVIDERS = {}
AUTH_PASSWORD_VALIDATORS = []

THROTTLE_USERS=["bob", "123"]

0 comments on commit 830c0ba

Please sign in to comment.