Skip to content

Commit

Permalink
Add throttling to contact api endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
jochenklar committed Jan 21, 2025
1 parent 0d35cd4 commit 46464f6
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 5 deletions.
14 changes: 14 additions & 0 deletions rdmo/core/assets/js/api/BaseApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ function BadRequestError(errors) {
this.errors = errors
}

function ThrottlingError(errors) {
this.errors = {
throttling: errors.detail
}
}

class BaseApi {

static get(url) {
Expand All @@ -31,6 +37,10 @@ class BaseApi {
return response.json().then(errors => {
throw new BadRequestError(errors)
})
} else if (response.status === 429) {
return response.json().then(errors => {
throw new ThrottlingError(errors)
})
} else {
throw new ApiError(response.statusText, response.status)
}
Expand Down Expand Up @@ -59,6 +69,10 @@ class BaseApi {
return response.json().then(errors => {
throw new ValidationError(errors)
})
} else if (response.status === 429) {
return response.json().then(errors => {
throw new ThrottlingError(errors)
})
} else {
throw new ApiError(response.statusText, response.status)
}
Expand Down
9 changes: 6 additions & 3 deletions rdmo/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'rdmo_default'
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'django_cache'
}
}

Expand All @@ -180,7 +180,10 @@
),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
)
),
'DEFAULT_THROTTLE_RATES': {
'email': '1/minute'
}
}

SETTINGS_EXPORT = [
Expand Down
8 changes: 8 additions & 0 deletions rdmo/core/throttling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from rest_framework.throttling import UserRateThrottle


class EmailThrottle(UserRateThrottle):
scope = 'email'

def allow_request(self, request, view):
return request.method == 'GET' or super().allow_request(request, view)
9 changes: 8 additions & 1 deletion rdmo/projects/assets/js/interview/components/main/Contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const Contact = ({ templates, contact, sendContact, closeContact }) => {
bsSize: 'lg'
}}>
<Html html={templates.project_interview_contact_help} />
<form onSubmit={onSubmit}>
<form className="mb-0" onSubmit={onSubmit}>
<div className="form-group">
<label htmlFor="interview-question-contact-subject">Subject</label>
<input
Expand Down Expand Up @@ -66,6 +66,13 @@ const Contact = ({ templates, contact, sendContact, closeContact }) => {
}
</ul>
</div>
{
errors && errors.throttling && (
<ul className="help-block list-unstyled mb-0">
<li className="text-danger">{errors.throttling}</li>
</ul>
)
}
</form>
</Modal>
</>
Expand Down
4 changes: 3 additions & 1 deletion rdmo/projects/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

from rdmo.conditions.models import Condition
from rdmo.core.permissions import HasModelPermission
from rdmo.core.throttling import EmailThrottle
from rdmo.core.utils import human2bytes, is_truthy, return_file_response
from rdmo.options.models import OptionSet
from rdmo.questions.models import Catalog, Page, Question, QuestionSet
Expand Down Expand Up @@ -329,7 +330,8 @@ def visibility(self, request, pk=None):
raise Http404

@action(detail=True, methods=['get', 'post'],
permission_classes=(HasModelPermission | HasProjectPermission, ))
permission_classes=(HasModelPermission | HasProjectPermission, ),
throttle_classes=[EmailThrottle])
def contact(self, request, pk):
if settings.PROJECT_CONTACT:
if request.method == 'POST':
Expand Down

0 comments on commit 46464f6

Please sign in to comment.