Merge pull request #26392 from edx/feanil/rate_limit_anon_csv

Feanil/rate limit anon csv
This commit is contained in:
Feanil Patel
2021-02-08 12:05:21 -05:00
committed by GitHub
2 changed files with 20 additions and 1 deletions

View File

@@ -25,6 +25,7 @@ from django.test import RequestFactory, TestCase
from django.urls import reverse as django_reverse
from django.utils.translation import ugettext as _
from edx_when.api import get_dates_for_course, get_overrides_for_user, set_date_for_block
from freezegun import freeze_time
from mock import Mock, NonCallableMock, patch
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locator import UsageKey
@@ -2781,8 +2782,11 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
"""
Test the CSV output for the anonymized user ids.
"""
base_time = datetime.datetime.now(UTC)
url = reverse('get_anon_ids', kwargs={'course_id': text_type(self.course.id)})
response = self.client.post(url, {})
with freeze_time(base_time):
response = self.client.post(url, {})
self.assertEqual(response['Content-Type'], 'text/csv')
body = response.content.decode("utf-8").replace('\r', '')
self.assertTrue(body.startswith(
@@ -2794,6 +2798,19 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
)
self.assertIn("attachment; filename=org", response['Content-Disposition'])
# Test rate-limiting
# The get_anon_ids view is computationally intensive and its execution time can vary
# depending on the number of enrollments in a course. We are rate limiting it to
# prevent too many concurrent calls which could result in a denial of service for
# other users of the lms.
with freeze_time(base_time + datetime.timedelta(minutes=1)):
response = self.client.post(url, {})
assert response.status_code == 403
with freeze_time(base_time + datetime.timedelta(minutes=5)):
response = self.client.post(url, {})
assert response.status_code == 200
@patch('lms.djangoapps.instructor_task.models.logger.error')
@patch.dict(settings.GRADES_DOWNLOAD, {'STORAGE_TYPE': 's3', 'ROOT_PATH': 'tmp/edx-s3/grades'})
def test_list_report_downloads_error(self, mock_error):

View File

@@ -34,6 +34,7 @@ from edx_rest_framework_extensions.auth.session.authentication import SessionAut
from edx_when.api import get_date_for_block
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey, UsageKey
from ratelimit.decorators import ratelimit
from rest_framework import status
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.response import Response
@@ -1381,6 +1382,7 @@ def get_proctored_exam_results(request, course_id):
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@ratelimit(key="user", rate="1/5m", block=True)
@require_course_permission(permissions.CAN_RESEARCH)
def get_anon_ids(request, course_id):
"""