Commit d929c1cd by Robert Raposa

Switch dashboard from GET to POST.

parent e8186a18
......@@ -18,7 +18,7 @@ from django.conf import settings
from django.contrib.auth.models import User
from django.core import mail
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse as django_reverse
from django.http import HttpRequest, HttpResponse
from django.test import RequestFactory, TestCase
from django.test.utils import override_settings
......@@ -33,7 +33,9 @@ from opaque_keys.edx.locator import UsageKey
from course_modes.models import CourseMode
from courseware.models import StudentModule
from courseware.tests.factories import StaffFactory, InstructorFactory, BetaTesterFactory, UserProfileFactory
from courseware.tests.factories import (
BetaTesterFactory, GlobalStaffFactory, InstructorFactory, StaffFactory, UserProfileFactory
)
from courseware.tests.helpers import LoginEnrollmentTestCase
from django_comment_common.models import FORUM_ROLE_COMMUNITY_TA
from django_comment_common.utils import seed_permissions_roles
......@@ -131,6 +133,81 @@ EXECUTIVE_SUMMARY_DATA = (
)
INSTRUCTOR_GET_ENDPOINTS = set([
'get_anon_ids',
'get_coupon_codes',
'get_issued_certificates',
'get_sale_order_records',
'get_sale_records',
])
INSTRUCTOR_POST_ENDPOINTS = set([
'active_registration_codes',
'add_users_to_cohorts',
'bulk_beta_modify_access',
'calculate_grades_csv',
'change_due_date',
'generate_registration_codes',
'get_enrollment_report',
'get_exec_summary_report',
'get_grading_config',
'get_problem_responses',
'get_proctored_exam_results',
'get_registration_codes',
'get_student_progress_url',
'get_students_features',
'get_students_who_may_enroll',
'get_user_invoice_preference',
'list_background_email_tasks',
'list_course_role_members',
'list_email_content',
'list_entrance_exam_instructor_tasks',
'list_financial_report_downloads',
'list_forum_members',
'list_instructor_tasks',
'list_report_downloads',
'mark_student_can_skip_entrance_exam',
'modify_access',
'register_and_enroll_students',
'rescore_entrance_exam',
'rescore_problem',
'reset_due_date',
'reset_student_attempts',
'reset_student_attempts_for_entrance_exam',
'sale_validation',
'show_student_extensions',
'show_unit_extensions',
'send_email',
'spent_registration_codes',
'students_update_enrollment',
'update_forum_role_membership',
])
def reverse(endpoint, args=None, kwargs=None, is_dashboard_endpoint=True):
"""
Simple wrapper of Django's reverse that first ensures that we have declared
each endpoint under test.
Arguments:
args: The args to be passed through to reverse.
endpoint: The endpoint to be passed through to reverse.
kwargs: The kwargs to be passed through to reverse.
is_dashboard_endpoint: True if this is an instructor dashboard endpoint
that must be declared in the INSTRUCTOR_GET_ENDPOINTS or
INSTRUCTOR_GET_ENDPOINTS sets, or false otherwise.
Returns:
The return of Django's reverse function
"""
is_endpoint_declared = endpoint in INSTRUCTOR_GET_ENDPOINTS or endpoint in INSTRUCTOR_POST_ENDPOINTS
if is_dashboard_endpoint and is_endpoint_declared is False:
# Verify that all endpoints are declared so we can ensure they are
# properly validated elsewhere.
raise ValueError("The endpoint {} must be declared in ENDPOINTS before use.".format(endpoint))
return django_reverse(endpoint, args=args, kwargs=kwargs)
@common_exceptions_400
def view_success(request): # pylint: disable=unused-argument
"A dummy view for testing that returns a simple HTTP response"
......@@ -192,6 +269,61 @@ class TestCommonExceptions400(TestCase):
@attr('shard_1')
@ddt.ddt
class TestEndpointHttpMethods(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
"""
Ensure that users can make GET requests against endpoints that allow GET,
and not against those that don't allow GET.
"""
@classmethod
def setUpClass(cls):
"""
Set up test course.
"""
super(TestEndpointHttpMethods, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self):
"""
Set up global staff role so authorization will not fail.
"""
super(TestEndpointHttpMethods, self).setUp()
global_user = GlobalStaffFactory()
self.client.login(username=global_user.username, password='test')
@ddt.data(*INSTRUCTOR_POST_ENDPOINTS)
def test_endpoints_reject_get(self, data):
"""
Tests that POST endpoints are rejected with 405 when using GET.
"""
url = reverse(data, kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url)
self.assertEqual(
response.status_code, 405,
"Endpoint {} returned status code {} instead of a 405. It should not allow GET.".format(
data, response.status_code
)
)
@ddt.data(*INSTRUCTOR_GET_ENDPOINTS)
def test_endpoints_accept_get(self, data):
"""
Tests that GET endpoints are not rejected with 405 when using GET.
"""
url = reverse(data, kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url)
self.assertNotEqual(
response.status_code, 405,
"Endpoint {} returned status code 405 where it shouldn't, since it should allow GET.".format(
data
)
)
@attr('shard_1')
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
@patch.dict(settings.FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True, 'REQUIRE_COURSE_EMAIL_AUTH': False})
class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
......@@ -265,10 +397,10 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
msg: message to display if assertion fails.
"""
url = reverse(endpoint, kwargs={'course_id': self.course.id.to_deprecated_string()})
if endpoint in ['send_email', 'students_update_enrollment', 'bulk_beta_modify_access']:
response = self.client.post(url, args)
else:
if endpoint in INSTRUCTOR_GET_ENDPOINTS:
response = self.client.get(url, args)
else:
response = self.client.post(url, args)
self.assertEqual(
response.status_code,
status_code,
......@@ -1798,13 +1930,13 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_modify_access_noparams(self):
""" Test missing all query parameters. """
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url)
response = self.client.post(url)
self.assertEqual(response.status_code, 400)
def test_modify_access_bad_action(self):
""" Test with an invalid action parameter. """
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.other_staff.email,
'rolename': 'staff',
'action': 'robot-not-an-action',
......@@ -1814,7 +1946,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_modify_access_bad_role(self):
""" Test with an invalid action parameter. """
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.other_staff.email,
'rolename': 'robot-not-a-roll',
'action': 'revoke',
......@@ -1823,7 +1955,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_modify_access_allow(self):
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.other_user.email,
'rolename': 'staff',
'action': 'allow',
......@@ -1832,7 +1964,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_modify_access_allow_with_uname(self):
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.other_instructor.username,
'rolename': 'staff',
'action': 'allow',
......@@ -1841,7 +1973,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_modify_access_revoke(self):
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.other_staff.email,
'rolename': 'staff',
'action': 'revoke',
......@@ -1850,7 +1982,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_modify_access_revoke_with_username(self):
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.other_staff.username,
'rolename': 'staff',
'action': 'revoke',
......@@ -1859,7 +1991,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_modify_access_with_fake_user(self):
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': 'GandalfTheGrey',
'rolename': 'staff',
'action': 'revoke',
......@@ -1876,7 +2008,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
self.other_user.is_active = False
self.other_user.save() # pylint: disable=no-member
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.other_user.username,
'rolename': 'beta',
'action': 'allow',
......@@ -1892,7 +2024,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_modify_access_revoke_not_allowed(self):
""" Test revoking access that a user does not have. """
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.other_staff.email,
'rolename': 'instructor',
'action': 'revoke',
......@@ -1904,7 +2036,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
Test that an instructor cannot remove instructor privelages from themself.
"""
url = reverse('modify_access', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.instructor.email,
'rolename': 'instructor',
'action': 'revoke',
......@@ -1923,20 +2055,20 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_list_course_role_members_noparams(self):
""" Test missing all query parameters. """
url = reverse('list_course_role_members', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url)
response = self.client.post(url)
self.assertEqual(response.status_code, 400)
def test_list_course_role_members_bad_rolename(self):
""" Test with an invalid rolename parameter. """
url = reverse('list_course_role_members', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'rolename': 'robot-not-a-rolename',
})
self.assertEqual(response.status_code, 400)
def test_list_course_role_members_staff(self):
url = reverse('list_course_role_members', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'rolename': 'staff',
})
self.assertEqual(response.status_code, 200)
......@@ -1958,7 +2090,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
def test_list_course_role_members_beta(self):
url = reverse('list_course_role_members', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'rolename': 'beta',
})
self.assertEqual(response.status_code, 200)
......@@ -1991,7 +2123,7 @@ class TestInstructorAPILevelsAccess(SharedModuleStoreTestCase, LoginEnrollmentTe
Get unique_student_identifier, rolename and action and update forum role.
"""
url = reverse('update_forum_role_membership', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(
response = self.client.post(
url,
{
'unique_student_identifier': identifier,
......@@ -2064,7 +2196,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
"""
enroll user using a registration code
"""
redeem_url = reverse('register_code_redemption', args=[code])
redeem_url = reverse('shoppingcart.views.register_code_redemption', args=[code], is_dashboard_endpoint=False)
self.client.login(username=user.username, password='test')
response = self.client.get(redeem_url)
self.assertEquals(response.status_code, 200)
......@@ -2144,10 +2276,16 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
mode_slug=CourseMode.HONOR
)
# update the quantity of the cart item paid_course_reg_item
resp = self.client.post(reverse('shoppingcart.views.update_user_cart'), {'ItemId': paid_course_reg_item.id, 'qty': '4'})
resp = self.client.post(
reverse('shoppingcart.views.update_user_cart', is_dashboard_endpoint=False),
{'ItemId': paid_course_reg_item.id, 'qty': '4'}
)
self.assertEqual(resp.status_code, 200)
# apply the coupon code to the item in the cart
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': coupon.code})
resp = self.client.post(
reverse('shoppingcart.views.use_code', is_dashboard_endpoint=False),
{'code': coupon.code}
)
self.assertEqual(resp.status_code, 200)
self.cart.purchase()
# get the updated item
......@@ -2156,7 +2294,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
coupon_redemption = CouponRedemption.objects.select_related('coupon').filter(order=self.cart)
sale_order_url = reverse('get_sale_order_records', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(sale_order_url)
response = self.client.post(sale_order_url)
self.assertEqual(response['Content-Type'], 'text/csv')
self.assertIn('36', response.content.split('\r\n')[1])
self.assertIn(str(item.unit_cost), response.content.split('\r\n')[1],)
......@@ -2180,11 +2318,18 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
PaidCourseRegistration.add_to_order(self.cart, self.course.id)
# apply the coupon code to the item in the cart
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': coupon.code})
resp = self.client.post(
reverse('shoppingcart.views.use_code', is_dashboard_endpoint=False),
{'code': coupon.code}
)
self.assertEqual(resp.status_code, 200)
# URL for instructor dashboard
instructor_dashboard = reverse('instructor_dashboard', kwargs={'course_id': self.course.id.to_deprecated_string()})
instructor_dashboard = reverse(
'instructor_dashboard',
kwargs={'course_id': self.course.id.to_deprecated_string()},
is_dashboard_endpoint=False
)
# visit the instructor dashboard page and
# check that the coupon redeem count should be 0
resp = self.client.get(instructor_dashboard)
......@@ -2221,7 +2366,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
'get_sale_records',
kwargs={'course_id': self.course.id.to_deprecated_string()}
)
response = self.client.get(url + '/csv', {})
response = self.client.post(url + '/csv', {})
self.assertEqual(response['Content-Type'], 'text/csv')
def test_get_sale_records_features_json(self):
......@@ -2240,7 +2385,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
course_registration_code.save()
url = reverse('get_sale_records', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertIn('sale', res_json)
......@@ -2290,7 +2435,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
course_registration_code.save()
url = reverse('get_sale_records', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertIn('sale', res_json)
......@@ -2338,7 +2483,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
)
problem_location = ''
response = self.client.get(url, {'problem_location': problem_location})
response = self.client.post(url, {'problem_location': problem_location})
res_json = json.loads(response.content)
self.assertEqual(res_json, 'Could not find problem with this location.')
......@@ -2373,7 +2518,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
)
problem_location = ''
response = self.client.get(url, {'problem_location': problem_location})
response = self.client.post(url, {'problem_location': problem_location})
res_json = json.loads(response.content)
self.assertIn('status', res_json)
status = res_json['status']
......@@ -2394,7 +2539,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
with patch('instructor_task.api.submit_calculate_problem_responses_csv') as submit_task_function:
error = AlreadyRunningError()
submit_task_function.side_effect = error
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertIn('status', res_json)
self.assertIn('already in progress', res_json['status'])
......@@ -2405,7 +2550,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
correctly in the response to get_students_features.
"""
url = reverse('get_students_features', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertIn('students', res_json)
for student in self.students:
......@@ -2425,7 +2570,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
url = reverse('get_students_features', kwargs={'course_id': unicode(self.course.id)})
set_course_cohort_settings(self.course.id, is_cohorted=is_cohorted)
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertEqual('cohort' in res_json['feature_names'], is_cohorted)
......@@ -2445,7 +2590,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
url = reverse('get_students_features', kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertEqual('team' in res_json['feature_names'], has_teams)
......@@ -2461,7 +2606,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
kwargs={'course_id': unicode(self.course.id)}
)
# Successful case:
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertIn('status', res_json)
self.assertNotIn('currently being created', res_json['status'])
......@@ -2469,7 +2614,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
with patch('instructor_task.api.submit_calculate_may_enroll_csv') as submit_task_function:
error = AlreadyRunningError()
submit_task_function.side_effect = error
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertIn('status', res_json)
self.assertIn('currently being created', res_json['status'])
......@@ -2484,7 +2629,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
kwargs={'course_id': unicode(self.course.id)}
)
# Successful case:
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertIn('status', res_json)
self.assertNotIn('currently being created', res_json['status'])
......@@ -2492,7 +2637,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
with patch('instructor_task.api.submit_proctored_exam_results_report') as submit_task_function:
error = AlreadyRunningError()
submit_task_function.side_effect = error
response = self.client.get(url, {})
response = self.client.post(url, {})
res_json = json.loads(response.content)
self.assertIn('status', res_json)
self.assertIn('currently being created', res_json['status'])
......@@ -2578,7 +2723,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
self.client.login(username=self.instructor.username, password='test')
url = reverse('get_enrollment_report', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertIn('The detailed enrollment report is being created.', response.content)
def test_bulk_purchase_detailed_report(self):
......@@ -2590,11 +2735,16 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
"""
paid_course_reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course.id)
# update the quantity of the cart item paid_course_reg_item
resp = self.client.post(reverse('shoppingcart.views.update_user_cart'),
{'ItemId': paid_course_reg_item.id, 'qty': '4'})
resp = self.client.post(
reverse('shoppingcart.views.update_user_cart', is_dashboard_endpoint=False),
{'ItemId': paid_course_reg_item.id, 'qty': '4'}
)
self.assertEqual(resp.status_code, 200)
# apply the coupon code to the item in the cart
resp = self.client.post(reverse('shoppingcart.views.use_code'), {'code': self.coupon_code})
resp = self.client.post(
reverse('shoppingcart.views.use_code', is_dashboard_endpoint=False),
{'code': self.coupon_code}
)
self.assertEqual(resp.status_code, 200)
self.cart.purchase()
......@@ -2628,7 +2778,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
self.client.login(username=self.instructor.username, password='test')
url = reverse('get_enrollment_report', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertIn('The detailed enrollment report is being created.', response.content)
def test_create_registration_code_without_invoice_and_order(self):
......@@ -2650,7 +2800,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
self.client.login(username=self.instructor.username, password='test')
url = reverse('get_enrollment_report', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertIn('The detailed enrollment report is being created.', response.content)
def test_invoice_payment_is_still_pending_for_registration_codes(self):
......@@ -2675,7 +2825,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
self.client.login(username=self.instructor.username, password='test')
url = reverse('get_enrollment_report', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertIn('The detailed enrollment report is being created.', response.content)
@patch.object(instructor.views.api, 'anonymous_id_for_user', Mock(return_value='42'))
......@@ -2685,7 +2835,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
Test the CSV output for the anonymized user ids.
"""
url = reverse('get_anon_ids', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertEqual(response['Content-Type'], 'text/csv')
body = response.content.replace('\r', '')
self.assertTrue(body.startswith(
......@@ -2703,7 +2853,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
('mock_file_name_1', 'https://1.mock.url'),
('mock_file_name_2', 'https://2.mock.url'),
]
response = self.client.get(url, {})
response = self.client.post(url, {})
expected_response = {
"downloads": [
......@@ -2732,12 +2882,12 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
success_status = "The {report_type} report is being created.".format(report_type=report_type)
if report_type == 'problem responses':
with patch(task_api_endpoint):
response = self.client.get(url, {'problem_location': ''})
response = self.client.post(url, {'problem_location': ''})
self.assertIn(success_status, response.content)
else:
CourseFinanceAdminRole(self.course.id).add_users(self.instructor)
with patch(task_api_endpoint):
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertIn(success_status, response.content)
@ddt.data(*EXECUTIVE_SUMMARY_DATA)
......@@ -2755,7 +2905,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
CourseFinanceAdminRole(self.course.id).add_users(self.instructor)
with patch(task_api_endpoint):
response = self.client.get(url, {})
response = self.client.post(url, {})
success_status = "The {report_type} report is being created." \
" To view the status of the report, see Pending" \
" Instructor Tasks" \
......@@ -2778,7 +2928,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
CourseFinanceAdminRole(self.course.id).add_users(self.instructor)
with patch(task_api_endpoint) as mock:
mock.side_effect = AlreadyRunningError()
response = self.client.get(url, {})
response = self.client.post(url, {})
already_running_status = "The {report_type} report is currently being created." \
" To view the status of the report, see Pending Instructor Tasks below." \
" You will be able to download the report" \
......@@ -2789,10 +2939,8 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
def test_get_student_progress_url(self):
""" Test that progress_url is in the successful response. """
url = reverse('get_student_progress_url', kwargs={'course_id': self.course.id.to_deprecated_string()})
url += "?unique_student_identifier={}".format(
quote(self.students[0].email.encode("utf-8"))
)
response = self.client.get(url)
data = {'unique_student_identifier': self.students[0].email.encode("utf-8")}
response = self.client.post(url, data)
self.assertEqual(response.status_code, 200)
res_json = json.loads(response.content)
self.assertIn('progress_url', res_json)
......@@ -2800,10 +2948,8 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
def test_get_student_progress_url_from_uname(self):
""" Test that progress_url is in the successful response. """
url = reverse('get_student_progress_url', kwargs={'course_id': self.course.id.to_deprecated_string()})
url += "?unique_student_identifier={}".format(
quote(self.students[0].username.encode("utf-8"))
)
response = self.client.get(url)
data = {'unique_student_identifier': self.students[0].username.encode("utf-8")}
response = self.client.post(url, data)
self.assertEqual(response.status_code, 200)
res_json = json.loads(response.content)
self.assertIn('progress_url', res_json)
......@@ -2811,13 +2957,13 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
def test_get_student_progress_url_noparams(self):
""" Test that the endpoint 404's without the required query params. """
url = reverse('get_student_progress_url', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url)
response = self.client.post(url)
self.assertEqual(response.status_code, 400)
def test_get_student_progress_url_nostudent(self):
""" Test that the endpoint 400's when requesting an unknown email. """
url = reverse('get_student_progress_url', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url)
response = self.client.post(url)
self.assertEqual(response.status_code, 400)
......@@ -2858,7 +3004,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_reset_student_attempts_deletall(self):
""" Make sure no one can delete all students state on a problem. """
url = reverse('reset_student_attempts', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': self.problem_urlname,
'all_students': True,
'delete_module': True,
......@@ -2868,7 +3014,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_reset_student_attempts_single(self):
""" Test reset single student attempts. """
url = reverse('reset_student_attempts', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': self.problem_urlname,
'unique_student_identifier': self.student.email,
})
......@@ -2885,7 +3031,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_reset_student_attempts_all(self, act):
""" Test reset all student attempts. """
url = reverse('reset_student_attempts', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': self.problem_urlname,
'all_students': True,
})
......@@ -2895,7 +3041,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_reset_student_attempts_missingmodule(self):
""" Test reset for non-existant problem. """
url = reverse('reset_student_attempts', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': 'robot-not-a-real-module',
'unique_student_identifier': self.student.email,
})
......@@ -2904,7 +3050,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_reset_student_attempts_delete(self):
""" Test delete single student state. """
url = reverse('reset_student_attempts', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': self.problem_urlname,
'unique_student_identifier': self.student.email,
'delete_module': True,
......@@ -2923,7 +3069,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_reset_student_attempts_nonsense(self):
""" Test failure with both unique_student_identifier and all_students. """
url = reverse('reset_student_attempts', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': self.problem_urlname,
'unique_student_identifier': self.student.email,
'all_students': True,
......@@ -2934,7 +3080,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_rescore_problem_single(self, act):
""" Test rescoring of a single student. """
url = reverse('rescore_problem', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': self.problem_urlname,
'unique_student_identifier': self.student.email,
})
......@@ -2945,7 +3091,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_rescore_problem_single_from_uname(self, act):
""" Test rescoring of a single student. """
url = reverse('rescore_problem', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': self.problem_urlname,
'unique_student_identifier': self.student.username,
})
......@@ -2956,7 +3102,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_rescore_problem_all(self, act):
""" Test rescoring for all students. """
url = reverse('rescore_problem', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'problem_to_reset': self.problem_urlname,
'all_students': True,
})
......@@ -2968,7 +3114,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
""" Test course has entrance exam id set while resetting attempts"""
url = reverse('reset_student_attempts_for_entrance_exam',
kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'all_students': True,
'delete_module': False,
})
......@@ -2978,7 +3124,7 @@ class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTes
def test_rescore_entrance_exam_with_invalid_exam(self):
""" Test course has entrance exam id set while re-scoring. """
url = reverse('rescore_entrance_exam', kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
})
self.assertEqual(response.status_code, 400)
......@@ -3058,7 +3204,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
""" Make sure no one can delete all students state on entrance exam. """
url = reverse('reset_student_attempts_for_entrance_exam',
kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'all_students': True,
'delete_module': True,
})
......@@ -3068,7 +3214,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
""" Test reset single student attempts for entrance exam. """
url = reverse('reset_student_attempts_for_entrance_exam',
kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
})
self.assertEqual(response.status_code, 200)
......@@ -3086,7 +3232,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
""" Test reset all student attempts for entrance exam. """
url = reverse('reset_student_attempts_for_entrance_exam',
kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'all_students': True,
})
self.assertEqual(response.status_code, 200)
......@@ -3096,7 +3242,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
""" Test reset for invalid entrance exam. """
url = reverse('reset_student_attempts_for_entrance_exam',
kwargs={'course_id': unicode(self.course_with_invalid_ee.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
})
self.assertEqual(response.status_code, 400)
......@@ -3105,7 +3251,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
""" Test delete single student entrance exam state. """
url = reverse('reset_student_attempts_for_entrance_exam',
kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
'delete_module': True,
})
......@@ -3121,7 +3267,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
self.client.login(username=staff_user.username, password='test')
url = reverse('reset_student_attempts_for_entrance_exam',
kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
'delete_module': True,
})
......@@ -3131,7 +3277,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
""" Test failure with both unique_student_identifier and all_students. """
url = reverse('reset_student_attempts_for_entrance_exam',
kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
'all_students': True,
})
......@@ -3141,7 +3287,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
def test_rescore_entrance_exam_single_student(self, act):
""" Test re-scoring of entrance exam for single student. """
url = reverse('rescore_entrance_exam', kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
})
self.assertEqual(response.status_code, 200)
......@@ -3150,7 +3296,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
def test_rescore_entrance_exam_all_student(self):
""" Test rescoring for all students. """
url = reverse('rescore_entrance_exam', kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'all_students': True,
})
self.assertEqual(response.status_code, 200)
......@@ -3158,7 +3304,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
def test_rescore_entrance_exam_all_student_and_single(self):
""" Test re-scoring with both all students and single student parameters. """
url = reverse('rescore_entrance_exam', kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
'all_students': True,
})
......@@ -3167,7 +3313,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
def test_rescore_entrance_exam_with_invalid_exam(self):
""" Test re-scoring of entrance exam with invalid exam. """
url = reverse('rescore_entrance_exam', kwargs={'course_id': unicode(self.course_with_invalid_ee.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
})
self.assertEqual(response.status_code, 400)
......@@ -3176,13 +3322,13 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
""" Test list task history for entrance exam AND student. """
# create a re-score entrance exam task
url = reverse('rescore_entrance_exam', kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
})
self.assertEqual(response.status_code, 200)
url = reverse('list_entrance_exam_instructor_tasks', kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
})
self.assertEqual(response.status_code, 200)
......@@ -3195,7 +3341,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
def test_list_entrance_exam_instructor_tasks_all_student(self):
""" Test list task history for entrance exam AND all student. """
url = reverse('list_entrance_exam_instructor_tasks', kwargs={'course_id': unicode(self.course.id)})
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertEqual(response.status_code, 200)
# check response
......@@ -3206,7 +3352,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
""" Test list task history for entrance exam failure if course has invalid exam. """
url = reverse('list_entrance_exam_instructor_tasks',
kwargs={'course_id': unicode(self.course_with_invalid_ee.id)})
response = self.client.get(url, {
response = self.client.post(url, {
'unique_student_identifier': self.student.email,
})
self.assertEqual(response.status_code, 400)
......@@ -3408,7 +3554,7 @@ class TestInstructorAPITaskLists(SharedModuleStoreTestCase, LoginEnrollmentTestC
mock_factory = MockCompletionInfo()
with patch('instructor.views.instructor_task_helpers.get_task_completion_info') as mock_completion_info:
mock_completion_info.side_effect = mock_factory.mock_get_task_completion_info
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertEqual(response.status_code, 200)
# check response
......@@ -3427,7 +3573,7 @@ class TestInstructorAPITaskLists(SharedModuleStoreTestCase, LoginEnrollmentTestC
mock_factory = MockCompletionInfo()
with patch('instructor.views.instructor_task_helpers.get_task_completion_info') as mock_completion_info:
mock_completion_info.side_effect = mock_factory.mock_get_task_completion_info
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertEqual(response.status_code, 200)
# check response
......@@ -3446,7 +3592,7 @@ class TestInstructorAPITaskLists(SharedModuleStoreTestCase, LoginEnrollmentTestC
mock_factory = MockCompletionInfo()
with patch('instructor.views.instructor_task_helpers.get_task_completion_info') as mock_completion_info:
mock_completion_info.side_effect = mock_factory.mock_get_task_completion_info
response = self.client.get(url, {
response = self.client.post(url, {
'problem_location_str': self.problem_urlname,
})
self.assertEqual(response.status_code, 200)
......@@ -3467,7 +3613,7 @@ class TestInstructorAPITaskLists(SharedModuleStoreTestCase, LoginEnrollmentTestC
mock_factory = MockCompletionInfo()
with patch('instructor.views.instructor_task_helpers.get_task_completion_info') as mock_completion_info:
mock_completion_info.side_effect = mock_factory.mock_get_task_completion_info
response = self.client.get(url, {
response = self.client.post(url, {
'problem_location_str': self.problem_urlname,
'unique_student_identifier': self.student.email,
})
......@@ -3528,7 +3674,7 @@ class TestInstructorEmailContentList(SharedModuleStoreTestCase, LoginEnrollmentT
url = reverse('list_email_content', kwargs={'course_id': self.course.id.to_deprecated_string()})
with patch('instructor.views.api.CourseEmail.objects.get') as mock_email_info:
mock_email_info.side_effect = self.get_matching_mock_email
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertEqual(response.status_code, 200)
return response
......@@ -3579,7 +3725,7 @@ class TestInstructorEmailContentList(SharedModuleStoreTestCase, LoginEnrollmentT
invalid_task.make_invalid_input()
task_history_request.return_value = [invalid_task]
url = reverse('list_email_content', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertEqual(response.status_code, 200)
self.assertTrue(task_history_request.called)
......@@ -3605,7 +3751,7 @@ class TestInstructorEmailContentList(SharedModuleStoreTestCase, LoginEnrollmentT
url = reverse('list_email_content', kwargs={'course_id': self.course.id.to_deprecated_string()})
with patch('instructor.views.api.CourseEmail.objects.get') as mock_email_info:
mock_email_info.return_value = email
response = self.client.get(url, {})
response = self.client.post(url, {})
self.assertEqual(response.status_code, 200)
self.assertTrue(task_history_request.called)
......@@ -3756,7 +3902,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
def test_change_due_date(self):
url = reverse('change_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'student': self.user1.username,
'url': self.week1.location.to_deprecated_string(),
'due_datetime': '12/30/2013 00:00'
......@@ -3767,7 +3913,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
def test_change_to_invalid_due_date(self):
url = reverse('change_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'student': self.user1.username,
'url': self.week1.location.to_deprecated_string(),
'due_datetime': '01/01/2009 00:00'
......@@ -3780,7 +3926,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
def test_change_nonexistent_due_date(self):
url = reverse('change_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'student': self.user1.username,
'url': self.week3.location.to_deprecated_string(),
'due_datetime': '12/30/2013 00:00'
......@@ -3794,7 +3940,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
def test_reset_date(self):
self.test_change_due_date()
url = reverse('reset_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'student': self.user1.username,
'url': self.week1.location.to_deprecated_string(),
})
......@@ -3806,7 +3952,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
def test_reset_nonexistent_extension(self):
url = reverse('reset_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'student': self.user1.username,
'url': self.week1.location.to_deprecated_string(),
})
......@@ -3823,7 +3969,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
self.week1 = self.store.update_item(self.week1, self.user1.id)
# Now, week1's normal due date is deleted but the extension still exists.
url = reverse('reset_due_date', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {
response = self.client.post(url, {
'student': self.user1.username,
'url': self.week1.location.to_deprecated_string(),
})
......@@ -3837,7 +3983,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
self.test_change_due_date()
url = reverse('show_unit_extensions',
kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {'url': self.week1.location.to_deprecated_string()})
response = self.client.post(url, {'url': self.week1.location.to_deprecated_string()})
self.assertEqual(response.status_code, 200, response.content)
self.assertEqual(json.loads(response.content), {
u'data': [{u'Extended Due Date': u'2013-12-30 00:00',
......@@ -3851,7 +3997,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
self.test_change_due_date()
url = reverse('show_student_extensions',
kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {'student': self.user1.username})
response = self.client.post(url, {'student': self.user1.username})
self.assertEqual(response.status_code, 200, response.content)
self.assertEqual(json.loads(response.content), {
u'data': [{u'Extended Due Date': u'2013-12-30 00:00',
......@@ -3898,14 +4044,14 @@ class TestCourseIssuedCertificatesData(SharedModuleStoreTestCase):
for __ in xrange(certificate_count):
self.generate_certificate(course_id=self.course.id, mode='honor', status=CertificateStatuses.generating)
response = self.client.get(url)
response = self.client.post(url)
res_json = json.loads(response.content)
self.assertIn('certificates', res_json)
self.assertEqual(len(res_json['certificates']), 0)
# Certificates with status 'downloadable' should be in response.
self.generate_certificate(course_id=self.course.id, mode='honor', status=CertificateStatuses.downloadable)
response = self.client.get(url)
response = self.client.post(url)
res_json = json.loads(response.content)
self.assertIn('certificates', res_json)
self.assertEqual(len(res_json['certificates']), 1)
......@@ -3920,7 +4066,7 @@ class TestCourseIssuedCertificatesData(SharedModuleStoreTestCase):
for __ in xrange(certificate_count):
self.generate_certificate(course_id=self.course.id, mode='honor', status=CertificateStatuses.downloadable)
response = self.client.get(url)
response = self.client.post(url)
res_json = json.loads(response.content)
self.assertIn('certificates', res_json)
self.assertEqual(len(res_json['certificates']), 1)
......@@ -3939,7 +4085,7 @@ class TestCourseIssuedCertificatesData(SharedModuleStoreTestCase):
status=CertificateStatuses.downloadable
)
response = self.client.get(url)
response = self.client.post(url)
res_json = json.loads(response.content)
self.assertIn('certificates', res_json)
......@@ -3956,14 +4102,13 @@ class TestCourseIssuedCertificatesData(SharedModuleStoreTestCase):
Test for certificate csv features.
"""
url = reverse('get_issued_certificates', kwargs={'course_id': unicode(self.course.id)})
url += '?csv=true'
# firstly generating downloadable certificates with 'honor' mode
certificate_count = 3
for __ in xrange(certificate_count):
self.generate_certificate(course_id=self.course.id, mode='honor', status=CertificateStatuses.downloadable)
current_date = datetime.date.today().strftime("%B %d, %Y")
response = self.client.get(url)
response = self.client.get(url, {'csv': 'true'})
self.assertEqual(response['Content-Type'], 'text/csv')
self.assertEqual(response['Content-Disposition'], 'attachment; filename={0}'.format('issued_certificates.csv'))
self.assertEqual(
......@@ -4412,7 +4557,7 @@ class TestCourseRegistrationCodes(SharedModuleStoreTestCase):
)
coupon.save()
response = self.client.get(get_coupon_code_url)
response = self.client.post(get_coupon_code_url)
self.assertEqual(response.status_code, 200, response.content)
# filter all the coupons
for coupon in Coupon.objects.all():
......@@ -4453,7 +4598,7 @@ class TestBulkCohorting(SharedModuleStoreTestCase):
self.tempdir = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, self.tempdir)
def call_add_users_to_cohorts(self, csv_data, suffix='.csv', method='POST'):
def call_add_users_to_cohorts(self, csv_data, suffix='.csv'):
"""
Call `add_users_to_cohorts` with a file generated from `csv_data`.
"""
......@@ -4463,10 +4608,7 @@ class TestBulkCohorting(SharedModuleStoreTestCase):
file_pointer.write(csv_data.encode('utf-8'))
with open(file_name, 'r') as file_pointer:
url = reverse('add_users_to_cohorts', kwargs={'course_id': unicode(self.course.id)})
if method == 'POST':
return self.client.post(url, {'uploaded-file': file_pointer})
elif method == 'GET':
return self.client.get(url, {'uploaded-file': file_pointer})
return self.client.post(url, {'uploaded-file': file_pointer})
def expect_error_on_file_content(self, file_content, error, file_suffix='.csv'):
"""
......@@ -4535,14 +4677,6 @@ class TestBulkCohorting(SharedModuleStoreTestCase):
response = self.call_add_users_to_cohorts('')
self.assertEqual(response.status_code, 403)
def test_post_only(self):
"""
Verify that we can't call the view when we aren't using POST.
"""
self.client.login(username=self.staff_user.username, password='test')
response = self.call_add_users_to_cohorts('', method='GET')
self.assertEqual(response.status_code, 405)
@patch('instructor.views.api.instructor_task.api.submit_cohort_students')
@patch('instructor.views.api.store_uploaded_file')
def test_success_username(self, mock_store_upload, mock_cohort_task):
......
......@@ -143,51 +143,14 @@ def common_exceptions_400(func):
return wrapped
def require_query_params(*args, **kwargs):
"""
Checks for required paremters or renders a 400 error.
(decorator with arguments)
`args` is a *list of required GET parameter names.
`kwargs` is a **dict of required GET parameter names
to string explanations of the parameter
"""
required_params = []
required_params += [(arg, None) for arg in args]
required_params += [(key, kwargs[key]) for key in kwargs]
# required_params = e.g. [('action', 'enroll or unenroll'), ['emails', None]]
def decorator(func): # pylint: disable=missing-docstring
def wrapped(*args, **kwargs): # pylint: disable=missing-docstring
request = args[0]
error_response_data = {
'error': 'Missing required query parameter(s)',
'parameters': [],
'info': {},
}
for (param, extra) in required_params:
default = object()
if request.GET.get(param, default) == default:
error_response_data['parameters'].append(param)
error_response_data['info'][param] = extra
if len(error_response_data['parameters']) > 0:
return JsonResponse(error_response_data, status=400)
else:
return func(*args, **kwargs)
return wrapped
return decorator
def require_post_params(*args, **kwargs):
"""
Checks for required parameters or renders a 400 error.
(decorator with arguments)
Functions like 'require_query_params', but checks for
POST parameters rather than GET parameters.
`args` is a *list of required POST parameter names.
`kwargs` is a **dict of required POST parameter names
to string explanations of the parameter
"""
required_params = []
required_params += [(arg, None) for arg in args]
......@@ -317,6 +280,7 @@ NAME_INDEX = 2
COUNTRY_INDEX = 3
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -517,6 +481,7 @@ def create_and_enroll_user(email, username, name, country, password, course_id):
return CourseEnrollment.enroll(user, course_id)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -681,6 +646,7 @@ def students_update_enrollment(request, course_id):
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('instructor')
......@@ -761,11 +727,12 @@ def bulk_beta_modify_access(request, course_id):
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('instructor')
@common_exceptions_400
@require_query_params(
@require_post_params(
unique_student_identifier="email or username of user to change access",
rolename="'instructor', 'staff', 'beta', or 'ccx_coach'",
action="'allow' or 'revoke'"
......@@ -787,10 +754,10 @@ def modify_access(request, course_id):
request.user, 'instructor', course_id, depth=None
)
try:
user = get_student_from_identifier(request.GET.get('unique_student_identifier'))
user = get_student_from_identifier(request.POST.get('unique_student_identifier'))
except User.DoesNotExist:
response_payload = {
'unique_student_identifier': request.GET.get('unique_student_identifier'),
'unique_student_identifier': request.POST.get('unique_student_identifier'),
'userDoesNotExist': True,
}
return JsonResponse(response_payload)
......@@ -805,8 +772,8 @@ def modify_access(request, course_id):
}
return JsonResponse(response_payload)
rolename = request.GET.get('rolename')
action = request.GET.get('action')
rolename = request.POST.get('rolename')
action = request.POST.get('action')
if rolename not in ROLES:
error = strip_tags("unknown rolename '{}'".format(rolename))
......@@ -841,10 +808,11 @@ def modify_access(request, course_id):
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('instructor')
@require_query_params(rolename="'instructor', 'staff', or 'beta'")
@require_post_params(rolename="'instructor', 'staff', or 'beta'")
def list_course_role_members(request, course_id):
"""
List instructors and staff.
......@@ -869,7 +837,7 @@ def list_course_role_members(request, course_id):
request.user, 'instructor', course_id, depth=None
)
rolename = request.GET.get('rolename')
rolename = request.POST.get('rolename')
if rolename not in ROLES:
return HttpResponseBadRequest()
......@@ -893,6 +861,7 @@ def list_course_role_members(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -909,7 +878,7 @@ def get_problem_responses(request, course_id):
Responds with BadRequest if problem location is faulty.
"""
course_key = CourseKey.from_string(course_id)
problem_location = request.GET.get('problem_location', '')
problem_location = request.POST.get('problem_location', '')
try:
problem_key = UsageKey.from_string(problem_location)
......@@ -938,6 +907,7 @@ def get_problem_responses(request, course_id):
return JsonResponse({"status": already_running_status})
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -1136,6 +1106,7 @@ def get_issued_certificates(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -1215,6 +1186,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -1322,6 +1294,7 @@ def get_coupon_codes(request, course_id): # pylint: disable=unused-argument
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -1346,6 +1319,7 @@ def get_enrollment_report(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -1371,6 +1345,7 @@ def get_exec_summary_report(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -1395,6 +1370,7 @@ def get_course_survey_results(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -1801,11 +1777,12 @@ def get_anon_ids(request, course_id): # pylint: disable=unused-argument
return csv_response(course_id.to_deprecated_string().replace('/', '-') + '-anon-ids.csv', header, rows)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@common_exceptions_400
@require_level('staff')
@require_query_params(
@require_post_params(
unique_student_identifier="email or username of student for whom to get progress url"
)
def get_student_progress_url(request, course_id):
......@@ -1813,13 +1790,13 @@ def get_student_progress_url(request, course_id):
Get the progress url of a student.
Limited to staff access.
Takes query paremeter unique_student_identifier and if the student exists
Takes query parameter unique_student_identifier and if the student exists
returns e.g. {
'progress_url': '/../...'
}
"""
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
user = get_student_from_identifier(request.GET.get('unique_student_identifier'))
user = get_student_from_identifier(request.POST.get('unique_student_identifier'))
progress_url = reverse('student_progress', kwargs={'course_id': course_id.to_deprecated_string(), 'student_id': user.id})
......@@ -1831,10 +1808,11 @@ def get_student_progress_url(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
@require_query_params(
@require_post_params(
problem_to_reset="problem urlname to reset"
)
@common_exceptions_400
......@@ -1861,13 +1839,13 @@ def reset_student_attempts(request, course_id):
request.user, 'staff', course_id, depth=None
)
problem_to_reset = strip_if_string(request.GET.get('problem_to_reset'))
student_identifier = request.GET.get('unique_student_identifier', None)
problem_to_reset = strip_if_string(request.POST.get('problem_to_reset'))
student_identifier = request.POST.get('unique_student_identifier', None)
student = None
if student_identifier is not None:
student = get_student_from_identifier(student_identifier)
all_students = request.GET.get('all_students', False) in ['true', 'True', True]
delete_module = request.GET.get('delete_module', False) in ['true', 'True', True]
all_students = request.POST.get('all_students', False) in ['true', 'True', True]
delete_module = request.POST.get('delete_module', False) in ['true', 'True', True]
# parameter combinations
if all_students and student:
......@@ -1913,6 +1891,7 @@ def reset_student_attempts(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -1943,12 +1922,12 @@ def reset_student_attempts_for_entrance_exam(request, course_id): # pylint: dis
_("Course has no entrance exam section.")
)
student_identifier = request.GET.get('unique_student_identifier', None)
student_identifier = request.POST.get('unique_student_identifier', None)
student = None
if student_identifier is not None:
student = get_student_from_identifier(student_identifier)
all_students = request.GET.get('all_students', False) in ['true', 'True', True]
delete_module = request.GET.get('delete_module', False) in ['true', 'True', True]
all_students = request.POST.get('all_students', False) in ['true', 'True', True]
delete_module = request.POST.get('delete_module', False) in ['true', 'True', True]
# parameter combinations
if all_students and student:
......@@ -1979,10 +1958,11 @@ def reset_student_attempts_for_entrance_exam(request, course_id): # pylint: dis
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('instructor')
@require_query_params(problem_to_reset="problem urlname to reset")
@require_post_params(problem_to_reset="problem urlname to reset")
@common_exceptions_400
def rescore_problem(request, course_id):
"""
......@@ -1997,13 +1977,13 @@ def rescore_problem(request, course_id):
all_students and unique_student_identifier cannot both be present.
"""
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
problem_to_reset = strip_if_string(request.GET.get('problem_to_reset'))
student_identifier = request.GET.get('unique_student_identifier', None)
problem_to_reset = strip_if_string(request.POST.get('problem_to_reset'))
student_identifier = request.POST.get('unique_student_identifier', None)
student = None
if student_identifier is not None:
student = get_student_from_identifier(student_identifier)
all_students = request.GET.get('all_students') in ['true', 'True', True]
all_students = request.POST.get('all_students') in ['true', 'True', True]
if not (problem_to_reset and (all_students or student)):
return HttpResponseBadRequest("Missing query parameters.")
......@@ -2035,6 +2015,7 @@ def rescore_problem(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('instructor')
......@@ -2055,12 +2036,12 @@ def rescore_entrance_exam(request, course_id):
request.user, 'staff', course_id, depth=None
)
student_identifier = request.GET.get('unique_student_identifier', None)
student_identifier = request.POST.get('unique_student_identifier', None)
student = None
if student_identifier is not None:
student = get_student_from_identifier(student_identifier)
all_students = request.GET.get('all_students') in ['true', 'True', True]
all_students = request.POST.get('all_students') in ['true', 'True', True]
if not course.entrance_exam_id:
return HttpResponseBadRequest(
......@@ -2087,6 +2068,7 @@ def rescore_entrance_exam(request, course_id):
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2105,6 +2087,7 @@ def list_background_email_tasks(request, course_id): # pylint: disable=unused-a
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2123,6 +2106,7 @@ def list_email_content(request, course_id): # pylint: disable=unused-argument
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2137,8 +2121,8 @@ def list_instructor_tasks(request, course_id):
history for problem AND student (intersection)
"""
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
problem_location_str = strip_if_string(request.GET.get('problem_location_str', False))
student = request.GET.get('unique_student_identifier', None)
problem_location_str = strip_if_string(request.POST.get('problem_location_str', False))
student = request.POST.get('unique_student_identifier', None)
if student is not None:
student = get_student_from_identifier(student)
......@@ -2168,6 +2152,7 @@ def list_instructor_tasks(request, course_id):
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2181,7 +2166,7 @@ def list_entrance_exam_instructor_tasks(request, course_id): # pylint: disable=
"""
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
course = get_course_by_id(course_id)
student = request.GET.get('unique_student_identifier', None)
student = request.POST.get('unique_student_identifier', None)
if student is not None:
student = get_student_from_identifier(student)
......@@ -2202,6 +2187,7 @@ def list_entrance_exam_instructor_tasks(request, course_id): # pylint: disable=
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2221,6 +2207,7 @@ def list_report_downloads(_request, course_id):
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2242,6 +2229,7 @@ def list_financial_report_downloads(_request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2265,6 +2253,7 @@ def calculate_grades_csv(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2291,10 +2280,11 @@ def problem_grade_report(request, course_id):
})
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
@require_query_params('rolename')
@require_post_params('rolename')
def list_forum_members(request, course_id):
"""
Lists forum members of a certain rolename.
......@@ -2313,7 +2303,7 @@ def list_forum_members(request, course_id):
request.user, course_id, FORUM_ROLE_ADMINISTRATOR
)
rolename = request.GET.get('rolename')
rolename = request.POST.get('rolename')
# default roles require either (staff & forum admin) or (instructor)
if not (has_forum_admin or has_instructor_access):
......@@ -2354,6 +2344,7 @@ def list_forum_members(request, course_id):
@transaction.non_atomic_requests
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
......@@ -2407,10 +2398,11 @@ def send_email(request, course_id):
return JsonResponse(response_payload)
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
@require_query_params(
@require_post_params(
unique_student_identifier="email or username of user to change access",
rolename="the forum role",
action="'allow' or 'revoke'",
......@@ -2437,9 +2429,9 @@ def update_forum_role_membership(request, course_id):
request.user, course_id, FORUM_ROLE_ADMINISTRATOR
)
unique_student_identifier = request.GET.get('unique_student_identifier')
rolename = request.GET.get('rolename')
action = request.GET.get('action')
unique_student_identifier = request.POST.get('unique_student_identifier')
rolename = request.POST.get('rolename')
action = request.POST.get('action')
# default roles require either (staff & forum admin) or (instructor)
if not (has_forum_admin or has_instructor_access):
......@@ -2497,18 +2489,19 @@ def _display_unit(unit):
@handle_dashboard_error
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
@require_query_params('student', 'url', 'due_datetime')
@require_post_params('student', 'url', 'due_datetime')
def change_due_date(request, course_id):
"""
Grants a due date extension to a student for a particular unit.
"""
course = get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(course_id))
student = require_student_from_identifier(request.GET.get('student'))
unit = find_unit(course, request.GET.get('url'))
due_date = parse_datetime(request.GET.get('due_datetime'))
student = require_student_from_identifier(request.POST.get('student'))
unit = find_unit(course, request.POST.get('url'))
due_date = parse_datetime(request.POST.get('due_datetime'))
set_due_date_extension(course, unit, student, due_date)
return JsonResponse(_(
......@@ -2518,17 +2511,18 @@ def change_due_date(request, course_id):
@handle_dashboard_error
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
@require_query_params('student', 'url')
@require_post_params('student', 'url')
def reset_due_date(request, course_id):
"""
Rescinds a due date extension for a student on a particular unit.
"""
course = get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(course_id))
student = require_student_from_identifier(request.GET.get('student'))
unit = find_unit(course, request.GET.get('url'))
student = require_student_from_identifier(request.POST.get('student'))
unit = find_unit(course, request.POST.get('url'))
set_due_date_extension(course, unit, student, None)
if not getattr(unit, "due", None):
# It's possible the normal due date was deleted after an extension was granted:
......@@ -2544,30 +2538,32 @@ def reset_due_date(request, course_id):
@handle_dashboard_error
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
@require_query_params('url')
@require_post_params('url')
def show_unit_extensions(request, course_id):
"""
Shows all of the students which have due date extensions for the given unit.
"""
course = get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(course_id))
unit = find_unit(course, request.GET.get('url'))
unit = find_unit(course, request.POST.get('url'))
return JsonResponse(dump_module_extensions(course, unit))
@handle_dashboard_error
@require_POST
@ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_level('staff')
@require_query_params('student')
@require_post_params('student')
def show_student_extensions(request, course_id):
"""
Shows all of the due date extensions granted to a particular student in a
particular course.
"""
student = require_student_from_identifier(request.GET.get('student'))
student = require_student_from_identifier(request.POST.get('student'))
course = get_course_by_id(SlashSeparatedCourseKey.from_deprecated_string(course_id))
return JsonResponse(dump_student_extensions(course, student))
......@@ -2922,7 +2918,6 @@ def generate_certificate_exceptions(request, course_id, generate_for=None):
return JsonResponse(response_payload)
@csrf_exempt
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
@require_global_staff
@require_POST
......
......@@ -109,6 +109,7 @@ class DataDownload
url = @$list_proctored_exam_results_csv_btn.data 'endpoint'
# display html from proctored exam results config endpoint
$.ajax
type: 'POST'
dataType: 'json'
url: url
error: (std_ajax_err) =>
......@@ -128,6 +129,7 @@ class DataDownload
url = @$survey_results_csv_btn.data 'endpoint'
# display html from survey results config endpoint
$.ajax
type: 'POST'
dataType: 'json'
url: url
error: (std_ajax_err) =>
......@@ -152,6 +154,7 @@ class DataDownload
url += '/csv'
$.ajax
type: 'POST'
dataType: 'json'
url: url
error: (std_ajax_err) =>
......@@ -170,6 +173,7 @@ class DataDownload
# fetch user list
$.ajax
type: 'POST'
dataType: 'json'
url: url
error: (std_ajax_err) =>
......@@ -198,6 +202,7 @@ class DataDownload
url = @$list_problem_responses_csv_btn.data 'endpoint'
$.ajax
type: 'POST'
dataType: 'json'
url: url
data:
......@@ -214,6 +219,7 @@ class DataDownload
url = @$list_may_enroll_csv_btn.data 'endpoint'
$.ajax
type: 'POST'
dataType: 'json'
url: url
error: (std_ajax_err) =>
......@@ -227,6 +233,7 @@ class DataDownload
url = @$grade_config_btn.data 'endpoint'
# display html from grading config endpoint
$.ajax
type: 'POST'
dataType: 'json'
url: url
error: (std_ajax_err) =>
......@@ -249,6 +256,7 @@ class DataDownload
@clear_display()
url = button.data 'endpoint'
$.ajax
type: 'POST'
dataType: 'json'
url: url
error: (std_ajax_err) =>
......
......@@ -45,6 +45,7 @@ class Extensions
due_datetime: @$due_datetime_input.val()
$.ajax
type: 'POST'
dataType: 'json'
url: @$change_due_date.data 'endpoint'
data: send_data
......@@ -60,6 +61,7 @@ class Extensions
url: @$url_input.val()
$.ajax
type: 'POST'
dataType: 'json'
url: @$reset_due_date.data 'endpoint'
data: send_data
......@@ -75,6 +77,7 @@ class Extensions
send_data =
url: @$url_input.val()
$.ajax
type: 'POST'
dataType: 'json'
url: url
data: send_data
......@@ -90,6 +93,7 @@ class Extensions
send_data =
student: @$student_input.val()
$.ajax
type: 'POST'
dataType: 'json'
url: url
data: send_data
......
......@@ -137,6 +137,7 @@ class AuthListWidget extends MemberListWidget
# `cb` is called with cb(error, member_list)
get_member_list: (cb) ->
$.ajax
type: 'POST'
dataType: 'json'
url: @list_endpoint
data: rolename: @rolename
......@@ -151,6 +152,7 @@ class AuthListWidget extends MemberListWidget
# `cb` is called with cb(error, data)
modify_member_access: (unique_student_identifier, action, cb) ->
$.ajax
type: 'POST'
dataType: 'json'
url: @modify_endpoint
data:
......@@ -645,6 +647,7 @@ class AuthList
# the endpoint comes from data-endpoint of the table
$.ajax
dataType: 'json'
type: 'POST'
url: @$display_table.data 'endpoint'
data: rolename: @rolename
success: load_auth_list
......@@ -664,6 +667,7 @@ class AuthList
access_change: (email, action, cb) ->
$.ajax
dataType: 'json'
type: 'POST'
url: @$add_section.data 'endpoint'
data:
email: email
......
......@@ -91,6 +91,7 @@ class SendEmail
@$btn_task_history_email.click =>
url = @$btn_task_history_email.data 'endpoint'
$.ajax
type: 'POST'
dataType: 'json'
url: url
success: (data) =>
......@@ -107,6 +108,7 @@ class SendEmail
@$btn_task_history_email_content.click =>
url = @$btn_task_history_email_content.data 'endpoint'
$.ajax
type: 'POST'
dataType: 'json'
url : url
success: (data) =>
......@@ -133,6 +135,7 @@ class SendEmail
$(".msg-confirm").css({"display":"block"})
# Email Section
class Email
# enable subsections.
......
......@@ -76,6 +76,7 @@ class @StudentAdmin
full_error_message = _.template(error_message, {student_id: unique_student_identifier})
$.ajax
type: 'POST'
dataType: 'json'
url: @$progress_link.data 'endpoint'
data: unique_student_identifier: unique_student_identifier
......@@ -101,6 +102,7 @@ class @StudentAdmin
full_error_message = _.template(error_message, {problem_id: problem_to_reset, student_id: unique_student_identifier})
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_reset_attempts_single.data 'endpoint'
data: send_data
......@@ -127,6 +129,7 @@ class @StudentAdmin
full_error_message = _.template(error_message, {student_id: unique_student_identifier, problem_id: problem_to_reset})
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_delete_state_single.data 'endpoint'
data: send_data
......@@ -153,6 +156,7 @@ class @StudentAdmin
full_error_message = _.template(error_message, {student_id: unique_student_identifier, problem_id: problem_to_reset})
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_rescore_problem_single.data 'endpoint'
data: send_data
......@@ -174,6 +178,7 @@ class @StudentAdmin
full_error_message = _.template(error_message, {student_id: unique_student_identifier, problem_id: problem_to_reset})
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_task_history_single.data 'endpoint'
data: send_data
......@@ -191,6 +196,7 @@ class @StudentAdmin
delete_module: false
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_reset_entrance_exam_attempts.data 'endpoint'
data: send_data
......@@ -212,6 +218,7 @@ class @StudentAdmin
unique_student_identifier: unique_student_identifier
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_rescore_entrance_exam.data 'endpoint'
data: send_data
......@@ -256,6 +263,7 @@ class @StudentAdmin
delete_module: true
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_delete_entrance_exam_state.data 'endpoint'
data: send_data
......@@ -277,6 +285,7 @@ class @StudentAdmin
unique_student_identifier: unique_student_identifier
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_entrance_exam_task_history.data 'endpoint'
data: send_data
......@@ -304,6 +313,7 @@ class @StudentAdmin
full_error_message = _.template(error_message, {problem_id: problem_to_reset})
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_reset_attempts_all.data 'endpoint'
data: send_data
......@@ -330,6 +340,7 @@ class @StudentAdmin
full_error_message = _.template(error_message, {problem_id: problem_to_reset})
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_rescore_problem_all.data 'endpoint'
data: send_data
......@@ -348,6 +359,7 @@ class @StudentAdmin
return @$request_response_error_all.text gettext("Please enter a problem location.")
$.ajax
type: 'POST'
dataType: 'json'
url: @$btn_task_history_all.data 'endpoint'
data: send_data
......
......@@ -284,6 +284,7 @@ class @PendingInstructorTasks
reload_running_tasks_list: =>
list_endpoint = @$table_running_tasks.data 'endpoint'
$.ajax
type: 'POST'
dataType: 'json'
url: list_endpoint
success: (data) =>
......@@ -340,6 +341,7 @@ class ReportDownloads
reload_report_downloads: ->
endpoint = @$report_downloads_table.data 'endpoint'
$.ajax
type: 'POST'
dataType: 'json'
url: endpoint
success: (data) =>
......
......@@ -39,6 +39,7 @@ var edx = edx || {};
$('input[name="user-enrollment-report"]').click(function(){
var url = $(this).data('endpoint');
$.ajax({
type: 'POST',
dataType: "json",
url: url,
success: function (data) {
......@@ -58,6 +59,7 @@ var edx = edx || {};
$('input[name="exec-summary-report"]').click(function(){
var url = $(this).data('endpoint');
$.ajax({
type: 'POST',
dataType: "json",
url: url,
success: function (data) {
......
......@@ -36,15 +36,15 @@ define(['jquery', 'coffee/src/instructor_dashboard/student_admin', 'common/js/sp
// Spy on AJAX requests
var requests = AjaxHelpers.requests(this);
studentadmin.$field_entrance_exam_student_select_grade.val(unique_student_identifier)
studentadmin.$field_entrance_exam_student_select_grade.val(unique_student_identifier);
studentadmin.$btn_reset_entrance_exam_attempts.click();
// Verify that the client contacts the server to start instructor task
var params = $.param({
unique_student_identifier: unique_student_identifier,
delete_module: false
});
var url = dashboard_api_url + '/reset_student_attempts_for_entrance_exam?' + params;
AjaxHelpers.expectJsonRequest(requests, 'GET', url);
var url = dashboard_api_url + '/reset_student_attempts_for_entrance_exam';
AjaxHelpers.expectPostRequest(requests, url, params);
// Simulate a success response from the server
AjaxHelpers.respondWithJson(requests, {
......@@ -63,8 +63,8 @@ define(['jquery', 'coffee/src/instructor_dashboard/student_admin', 'common/js/sp
unique_student_identifier: unique_student_identifier,
delete_module: false
});
var url = dashboard_api_url + '/reset_student_attempts_for_entrance_exam?' + params;
AjaxHelpers.expectJsonRequest(requests, 'GET', url);
var url = dashboard_api_url + '/reset_student_attempts_for_entrance_exam';
AjaxHelpers.expectPostRequest(requests, url, params);
// Simulate an error response from the server
AjaxHelpers.respondWithError(requests, 400,{});
......@@ -96,8 +96,8 @@ define(['jquery', 'coffee/src/instructor_dashboard/student_admin', 'common/js/sp
var params = $.param({
unique_student_identifier: unique_student_identifier
});
var url = dashboard_api_url + '/rescore_entrance_exam?' + params;
AjaxHelpers.expectJsonRequest(requests, 'GET', url);
var url = dashboard_api_url + '/rescore_entrance_exam';
AjaxHelpers.expectPostRequest(requests, url, params);
// Simulate a success response from the server
AjaxHelpers.respondWithJson(requests, {
......@@ -115,8 +115,8 @@ define(['jquery', 'coffee/src/instructor_dashboard/student_admin', 'common/js/sp
var params = $.param({
unique_student_identifier: unique_student_identifier
});
var url = dashboard_api_url + '/rescore_entrance_exam?' + params;
AjaxHelpers.expectJsonRequest(requests, 'GET', url);
var url = dashboard_api_url + '/rescore_entrance_exam';
AjaxHelpers.expectPostRequest(requests, url, params);
// Simulate an error response from the server
AjaxHelpers.respondWithError(requests, 400,{});
......@@ -195,8 +195,8 @@ define(['jquery', 'coffee/src/instructor_dashboard/student_admin', 'common/js/sp
unique_student_identifier: unique_student_identifier,
delete_module: true
});
var url = dashboard_api_url + '/reset_student_attempts_for_entrance_exam?' + params;
AjaxHelpers.expectJsonRequest(requests, 'GET', url);
var url = dashboard_api_url + '/reset_student_attempts_for_entrance_exam';
AjaxHelpers.expectPostRequest(requests, url, params);
// Simulate a success response from the server
AjaxHelpers.respondWithJson(requests, {
......@@ -215,8 +215,8 @@ define(['jquery', 'coffee/src/instructor_dashboard/student_admin', 'common/js/sp
unique_student_identifier: unique_student_identifier,
delete_module: true
});
var url = dashboard_api_url + '/reset_student_attempts_for_entrance_exam?' + params;
AjaxHelpers.expectJsonRequest(requests, 'GET', url);
var url = dashboard_api_url + '/reset_student_attempts_for_entrance_exam';
AjaxHelpers.expectPostRequest(requests, url, params);
// Simulate an error response from the server
AjaxHelpers.respondWithError(requests, 400,{});
......@@ -248,8 +248,8 @@ define(['jquery', 'coffee/src/instructor_dashboard/student_admin', 'common/js/sp
var params = $.param({
unique_student_identifier: unique_student_identifier
});
var url = dashboard_api_url + '/list_entrance_exam_instructor_tasks?' + params;
AjaxHelpers.expectJsonRequest(requests, 'GET', url);
var url = dashboard_api_url + '/list_entrance_exam_instructor_tasks';
AjaxHelpers.expectPostRequest(requests, url, params);
// Simulate a success response from the server
AjaxHelpers.respondWithJson(requests, {
......@@ -279,8 +279,8 @@ define(['jquery', 'coffee/src/instructor_dashboard/student_admin', 'common/js/sp
var params = $.param({
unique_student_identifier: unique_student_identifier
});
var url = dashboard_api_url + '/list_entrance_exam_instructor_tasks?' + params;
AjaxHelpers.expectJsonRequest(requests, 'GET', url);
var url = dashboard_api_url + '/list_entrance_exam_instructor_tasks';
AjaxHelpers.expectPostRequest(requests, url, params);
// Simulate an error response from the server
AjaxHelpers.respondWithError(requests, 400,{});
......
......@@ -87,7 +87,7 @@ define([
spyOn($, 'ajax');
StaffDebug.reset(locationName, location);
expect($.ajax.mostRecentCall.args[0]['type']).toEqual('GET');
expect($.ajax.mostRecentCall.args[0]['type']).toEqual('POST');
expect($.ajax.mostRecentCall.args[0]['data']).toEqual({
'problem_to_reset': location,
'unique_student_identifier': 'userman',
......@@ -106,7 +106,7 @@ define([
spyOn($, 'ajax');
StaffDebug.sdelete(locationName, location);
expect($.ajax.mostRecentCall.args[0]['type']).toEqual('GET');
expect($.ajax.mostRecentCall.args[0]['type']).toEqual('POST');
expect($.ajax.mostRecentCall.args[0]['data']).toEqual({
'problem_to_reset': location,
'unique_student_identifier': 'userman',
......@@ -126,7 +126,7 @@ define([
spyOn($, 'ajax');
StaffDebug.rescore(locationName, location);
expect($.ajax.mostRecentCall.args[0]['type']).toEqual('GET');
expect($.ajax.mostRecentCall.args[0]['type']).toEqual('POST');
expect($.ajax.mostRecentCall.args[0]['data']).toEqual({
'problem_to_reset': location,
'unique_student_identifier': 'userman',
......
......@@ -31,7 +31,7 @@ var StaffDebug = (function (){
'delete_module': action.delete_module
};
$.ajax({
type: "GET",
type: "POST",
url: get_url(action.method),
data: pdata,
success: function(data){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment