diff --git a/cms/djangoapps/contentstore/views/checklist.py b/cms/djangoapps/contentstore/views/checklist.py index 5a7658542ad50f58a063c9e5a7ed15232da6ed67..fa0a7b7b62f673f68e8ff663c9c4d921545e84de 100644 --- a/cms/djangoapps/contentstore/views/checklist.py +++ b/cms/djangoapps/contentstore/views/checklist.py @@ -3,6 +3,7 @@ import json from util.json_request import JsonResponse from django.http import HttpResponseBadRequest from django.contrib.auth.decorators import login_required +from django.views.decorators.http import require_http_methods from django_future.csrf import ensure_csrf_cookie from mitxmako.shortcuts import render_to_response @@ -10,7 +11,6 @@ from xmodule.modulestore import Location from xmodule.modulestore.inheritance import own_metadata from ..utils import get_modulestore, get_url_reverse -from .requests import get_request_method from .access import get_location_and_verify_access __all__ = ['get_checklists', 'update_checklist'] @@ -47,6 +47,7 @@ def get_checklists(request, org, course, name): }) +@require_http_methods(("GET", "POST", "PUT")) @ensure_csrf_cookie @login_required def update_checklist(request, org, course, name, checklist_index=None): @@ -63,8 +64,7 @@ def update_checklist(request, org, course, name, checklist_index=None): modulestore = get_modulestore(location) course_module = modulestore.get_item(location) - real_method = get_request_method(request) - if real_method == 'POST' or real_method == 'PUT': + if request.method in ("POST", "PUT"): if checklist_index is not None and 0 <= int(checklist_index) < len(course_module.checklists): index = int(checklist_index) course_module.checklists[index] = json.loads(request.body) @@ -83,8 +83,6 @@ def update_checklist(request, org, course, name, checklist_index=None): if modified: modulestore.update_metadata(location, own_metadata(course_module)) return JsonResponse(checklists) - else: - return HttpResponseBadRequest("Unsupported request.", content_type="text/plain") def expand_checklist_action_urls(course_module): diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index c4fb9277040217ab7f1a6e136d609ecc89d10184..fcf024d682762db99070992ab7269dd5f32ce4ac 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -4,6 +4,7 @@ from collections import defaultdict from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden from django.contrib.auth.decorators import login_required +from django.views.decorators.http import require_http_methods from django.core.exceptions import PermissionDenied from django_future.csrf import ensure_csrf_cookie from django.conf import settings @@ -23,7 +24,7 @@ from contentstore.utils import get_modulestore, get_lms_link_for_item, \ from models.settings.course_grading import CourseGradingModel -from .requests import get_request_method, _xmodule_recurse +from .requests import _xmodule_recurse from .access import has_access __all__ = ['OPEN_ENDED_COMPONENT_TYPES', @@ -288,6 +289,7 @@ def unpublish_unit(request): @expect_json +@require_http_methods(("GET", "POST", "PUT")) @login_required @ensure_csrf_cookie def module_info(request, module_location): @@ -297,8 +299,6 @@ def module_info(request, module_location): if not has_access(request.user, location): raise PermissionDenied() - real_method = get_request_method(request) - rewrite_static_links = request.GET.get('rewrite_url_links', 'True') in ['True', 'true'] logging.debug('rewrite_static_links = {0} {1}'.format(request.GET.get('rewrite_url_links', 'False'), rewrite_static_links)) @@ -306,9 +306,7 @@ def module_info(request, module_location): if not has_access(request.user, location): raise PermissionDenied() - if real_method == 'GET': + if request.method == 'GET': return JsonResponse(get_module_info(get_modulestore(location), location, rewrite_static_links=rewrite_static_links)) - elif real_method == 'POST' or real_method == 'PUT': + elif request.method in ("POST", "PUT"): return JsonResponse(set_module_info(get_modulestore(location), location, request.POST)) - else: - return HttpResponseBadRequest() diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index a7917d86697c325bbb3c57c4619e802f738b778b..0405112ea1263c0e37ebc8a18a76cc5b2011d41e 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -36,7 +36,6 @@ from auth.authz import create_all_course_groups, is_user_in_creator_group from util.json_request import expect_json from .access import has_access, get_location_and_verify_access -from .requests import get_request_method from .tabs import initialize_course_tabs from .component import ( OPEN_ENDED_COMPONENT_TYPES, NOTE_COMPONENT_TYPES, @@ -199,11 +198,9 @@ def course_info_updates(request, org, course, provided_id=None): if not has_access(request.user, location): raise PermissionDenied() - real_method = get_request_method(request) - if request.method == 'GET': return JsonResponse(get_course_updates(location)) - elif real_method == 'DELETE': + elif request.method == 'DELETE': try: return JsonResponse(delete_course_update(location, request.POST, provided_id)) except: @@ -308,6 +305,7 @@ def course_settings_updates(request, org, course, name, section): @expect_json +@require_http_methods(("GET", "POST", "PUT", "DELETE")) @login_required @ensure_csrf_cookie def course_grader_updates(request, org, course, name, grader_index=None): @@ -320,20 +318,19 @@ def course_grader_updates(request, org, course, name, grader_index=None): location = get_location_and_verify_access(request, org, course, name) - real_method = get_request_method(request) - - if real_method == 'GET': + if request.method == 'GET': # Cannot just do a get w/o knowing the course name :-( return JsonResponse(CourseGradingModel.fetch_grader(Location(location), grader_index)) - elif real_method == "DELETE": + elif request.method == "DELETE": # ??? Should this return anything? Perhaps success fail? CourseGradingModel.delete_grader(Location(location), grader_index) return JsonResponse() - elif request.method == 'POST': # post or put, doesn't matter. + else: # post or put, doesn't matter. return JsonResponse(CourseGradingModel.update_grader_from_json(Location(location), request.POST)) # # NB: expect_json failed on ["key", "key2"] and json payload +@require_http_methods(("GET", "POST", "PUT", "DELETE")) @login_required @ensure_csrf_cookie def course_advanced_updates(request, org, course, name): @@ -345,13 +342,11 @@ def course_advanced_updates(request, org, course, name): """ location = get_location_and_verify_access(request, org, course, name) - real_method = get_request_method(request) - - if real_method == 'GET': + if request.method == 'GET': return JsonResponse(CourseMetadata.fetch(location)) - elif real_method == 'DELETE': + elif request.method == 'DELETE': return JsonResponse(CourseMetadata.delete_key(location, json.loads(request.body))) - elif real_method == 'POST' or real_method == 'PUT': + else: # NOTE: request.POST is messed up because expect_json # cloned_request.POST.copy() is creating a defective entry w/ the whole payload as the key request_body = json.loads(request.body) diff --git a/cms/djangoapps/contentstore/views/requests.py b/cms/djangoapps/contentstore/views/requests.py index c493441c77379781873791941272d8dd1c39a15a..1385eaddba6b2daedeaae790f4bb3e4ae922f0ee 100644 --- a/cms/djangoapps/contentstore/views/requests.py +++ b/cms/djangoapps/contentstore/views/requests.py @@ -24,20 +24,6 @@ def event(request): return HttpResponse(status=204) -def get_request_method(request): - """ - Using HTTP_X_HTTP_METHOD_OVERRIDE, in the request metadata, determine - what type of request came from the client, and return it. - """ - # NB: we're setting Backbone.emulateHTTP to true on the client so everything comes as a post!!! - if request.method == 'POST' and 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META: - real_method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE'] - else: - real_method = request.method - - return real_method - - def create_json_response(errmsg=None): if errmsg is not None: resp = HttpResponse(json.dumps({'Status': 'Failed', 'ErrMsg': errmsg})) diff --git a/cms/envs/common.py b/cms/envs/common.py index 0d8412bee2c321fd56a2936afd33ba235318c382..1207b8fe059925569388edbef719d4f73ff043a4 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -143,6 +143,7 @@ MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', + 'method_override.middleware.MethodOverrideMiddleware', # Instead of AuthenticationMiddleware, we use a cache-backed version 'cache_toolbox.middleware.CacheBackedAuthenticationMiddleware', @@ -325,6 +326,7 @@ INSTALLED_APPS = ( 'django.contrib.messages', 'djcelery', 'south', + 'method_override', # Monitor the status of services 'service_status', diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 1117b67d029a3736535b6f6eed11bead798713dd..910b6f3defc3a8c16025cce74749cbf932adc755 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -19,6 +19,7 @@ django-sekizai==0.6.1 django-ses==0.4.1 django-storages==1.1.5 django-threaded-multihost==1.4-1 +django-method-override==0.1.0 django==1.4.5 feedparser==5.1.3 fs==0.4.0