[Backport] Throttling membership creation

remotes/origin/issue/4217/improving-mail-design
Alejandro Alonso 2017-01-04 08:42:57 +01:00
parent ed9ddf9aa9
commit ec049521e4
5 changed files with 32 additions and 13 deletions

View File

@ -424,7 +424,7 @@ REST_FRAMEWORK = {
"user": None,
"import-mode": None,
"import-dump-mode": "1/minute",
"memberships": None,
"create-memberships": None
},
"FILTER_BACKEND": "taiga.base.filters.FilterBackend",
"EXCEPTION_HANDLER": "taiga.base.exceptions.exception_handler",

View File

@ -33,5 +33,5 @@ REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"] = {
"user": None,
"import-mode": None,
"import-dump-mode": None,
"memberships": None,
"create-memberships": None,
}

View File

@ -153,11 +153,15 @@ class SimpleRateThrottle(BaseThrottle):
# throttle duration
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
return self.throttle_success()
def throttle_success(self):
if self.exceeded_throttling_restriction(request, view):
return self.throttle_failure()
return self.throttle_success(request, view)
def exceeded_throttling_restriction(self, request, view):
return len(self.history) >= self.num_requests
def throttle_success(self, request, view):
"""
Inserts the current request's timestamp along with the key
into the cache.

View File

@ -20,5 +20,20 @@ from taiga.base import throttling
class MembershipsRateThrottle(throttling.UserRateThrottle):
scope = "memberships"
scope = "create-memberships"
throttled_methods = ["POST", "PUT"]
def exceeded_throttling_restriction(self, request, view):
self.created_memberships = 0
if view.action in ["create", "resend_invitation"]:
self.created_memberships = 1
elif view.action == "bulk_create":
self.created_memberships = len(request.DATA.get("bulk_memberships", []))
return len(self.history) + self.created_memberships > self.num_requests
def throttle_success(self, request, view):
for i in range(self.created_memberships):
self.history.insert(0, self.now)
self.cache.set(self.key, self.history, self.duration)
return True

View File

@ -606,7 +606,7 @@ def test_api_create_bulk_members_max_pending_memberships(client, settings):
def test_create_memberhips_throttling(client, settings):
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["memberships"] = "1/minute"
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["create-memberships"] = "1/minute"
membership = f.MembershipFactory(is_admin=True)
role = f.RoleFactory.create(project=membership.project)
@ -625,11 +625,11 @@ def test_create_memberhips_throttling(client, settings):
response = client.json.post(url, json.dumps(data))
assert response.status_code == 429
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["memberships"] = None
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["create-memberships"] = None
def test_api_resend_invitation_throttling(client, outbox, settings):
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["memberships"] = "1/minute"
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["create-memberships"] = "1/minute"
invitation = f.create_invitation(user=None)
f.MembershipFactory(project=invitation.project, user=invitation.project.owner, is_admin=True)
@ -647,11 +647,11 @@ def test_api_resend_invitation_throttling(client, outbox, settings):
assert response.status_code == 429
assert len(outbox) == 1
assert outbox[0].to == [invitation.email]
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["memberships"] = None
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["create-memberships"] = None
def test_api_create_bulk_members_throttling(client, settings):
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["memberships"] = "1/minute"
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["create-memberships"] = "2/minute"
project = f.ProjectFactory()
john = f.UserFactory.create()
@ -686,4 +686,4 @@ def test_api_create_bulk_members_throttling(client, settings):
response = client.json.post(url, json.dumps(data))
assert response.status_code == 429
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["memberships"] = None
settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["create-memberships"] = None