From 5bf38f5416901bfe07a77440092fb315037e5b4d Mon Sep 17 00:00:00 2001 From: stvn Date: Fri, 15 May 2020 14:41:25 -0700 Subject: [PATCH 1/2] Convert masquerade view to class-based --- lms/djangoapps/courseware/masquerade.py | 81 ++++++++++++---------- lms/djangoapps/courseware/tests/helpers.py | 5 +- lms/urls.py | 4 +- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/lms/djangoapps/courseware/masquerade.py b/lms/djangoapps/courseware/masquerade.py index 515b7e2ebe..5defc30911 100644 --- a/lms/djangoapps/courseware/masquerade.py +++ b/lms/djangoapps/courseware/masquerade.py @@ -12,8 +12,9 @@ from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.db.models import Q +from django.utils.decorators import method_decorator from django.utils.translation import ugettext as _ -from django.views.decorators.http import require_POST +from django.views import View from opaque_keys.edx.keys import CourseKey from pytz import utc from web_fragments.fragment import Fragment @@ -62,44 +63,50 @@ class CourseMasquerade(object): self.__init__(**state) -@require_POST -@login_required -@expect_json -def handle_ajax(request, course_key_string): +@method_decorator(login_required, name='dispatch') +class MasqueradeView(View): """ - Handle AJAX posts to update the current user's masquerade for the specified course. - The masquerade settings are stored in the Django session as a dict from course keys - to CourseMasquerade objects. + Create an HTTP endpoint to manage masquerade settings """ - course_key = CourseKey.from_string(course_key_string) - masquerade_settings = request.session.get(MASQUERADE_SETTINGS_KEY, {}) - request_json = request.json - role = request_json.get('role', 'student') - group_id = request_json.get('group_id', None) - user_partition_id = request_json.get('user_partition_id', None) if group_id is not None else None - user_name = request_json.get('user_name', None) - found_user_name = None - if user_name: - users_in_course = CourseEnrollment.objects.users_enrolled_in(course_key) - try: - found_user_name = users_in_course.get(Q(email=user_name) | Q(username=user_name)).username - except User.DoesNotExist: - return JsonResponse({ - 'success': False, - 'error': _( - u'There is no user with the username or email address u"{user_identifier}" ' - 'enrolled in this course.' - ).format(user_identifier=user_name) - }) - masquerade_settings[course_key] = CourseMasquerade( - course_key, - role=role, - user_partition_id=user_partition_id, - group_id=group_id, - user_name=found_user_name, - ) - request.session[MASQUERADE_SETTINGS_KEY] = masquerade_settings - return JsonResponse({'success': True}) + + @method_decorator(expect_json) + def post(self, request, course_key_string): + """ + Handle AJAX posts to update the current user's masquerade for the specified course. + The masquerade settings are stored in the Django session as a dict from course keys + to CourseMasquerade objects. + """ + course_key = CourseKey.from_string(course_key_string) + masquerade_settings = request.session.get(MASQUERADE_SETTINGS_KEY, {}) + request_json = request.json + role = request_json.get('role', 'student') + group_id = request_json.get('group_id', None) + user_partition_id = request_json.get('user_partition_id', None) if group_id is not None else None + user_name = request_json.get('user_name', None) + found_user_name = None + if user_name: + users_in_course = CourseEnrollment.objects.users_enrolled_in(course_key) + try: + found_user_name = users_in_course.get(Q(email=user_name) | Q(username=user_name)).username + except User.DoesNotExist: + return JsonResponse({ + 'success': False, + 'error': _( + u'There is no user with the username or email address u"{user_identifier}" ' + 'enrolled in this course.' + ).format( + user_identifier=user_name, + ), + }) + masquerade_settings[course_key] = CourseMasquerade( + course_key, + role=role, + user_partition_id=user_partition_id, + group_id=group_id, + user_name=found_user_name, + ) + request.session[MASQUERADE_SETTINGS_KEY] = masquerade_settings + return JsonResponse({'success': True}) def setup_masquerade(request, course_key, staff_access=False, reset_masquerade_data=False): diff --git a/lms/djangoapps/courseware/tests/helpers.py b/lms/djangoapps/courseware/tests/helpers.py index 00f0e9ca97..be4da4753b 100644 --- a/lms/djangoapps/courseware/tests/helpers.py +++ b/lms/djangoapps/courseware/tests/helpers.py @@ -22,7 +22,8 @@ from xblock.field_data import DictFieldData from edxmako.shortcuts import render_to_string from lms.djangoapps.courseware.access import has_access from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link -from lms.djangoapps.courseware.masquerade import handle_ajax, setup_masquerade +from lms.djangoapps.courseware.masquerade import MasqueradeView +from lms.djangoapps.courseware.masquerade import setup_masquerade from lms.djangoapps.lms_xblock.field_data import LmsFieldData from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.lib.url_utils import quote_slashes @@ -348,7 +349,7 @@ def masquerade_as_group_member(user, course, partition_id, group_id): user, data={"role": "student", "user_partition_id": partition_id, "group_id": group_id} ) - response = handle_ajax(request, six.text_type(course.id)) + response = MasqueradeView.as_view()(request, six.text_type(course.id)) setup_masquerade(request, course.id, True) return response.status_code diff --git a/lms/urls.py b/lms/urls.py index 6e6c1943a7..236cd486fe 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -15,7 +15,7 @@ from ratelimitbackend import admin from branding import views as branding_views from debug import views as debug_views from lms.djangoapps.certificates import views as certificates_views -from lms.djangoapps.courseware.masquerade import handle_ajax as courseware_masquerade_handle_ajax +from lms.djangoapps.courseware.masquerade import MasqueradeView from lms.djangoapps.courseware.module_render import ( handle_xblock_callback, handle_xblock_callback_noauth, @@ -721,7 +721,7 @@ if settings.FEATURES.get('ENABLE_MASQUERADE'): r'^courses/{}/masquerade$'.format( settings.COURSE_KEY_PATTERN, ), - courseware_masquerade_handle_ajax, + MasqueradeView.as_view(), name='masquerade_update', ), ] From 69417396aa36f71883f6533651519b1af7872b81 Mon Sep 17 00:00:00 2001 From: stvn Date: Fri, 15 May 2020 14:42:02 -0700 Subject: [PATCH 2/2] Add is_staff check to masquerade POST --- lms/djangoapps/courseware/masquerade.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lms/djangoapps/courseware/masquerade.py b/lms/djangoapps/courseware/masquerade.py index 5defc30911..fc266913af 100644 --- a/lms/djangoapps/courseware/masquerade.py +++ b/lms/djangoapps/courseware/masquerade.py @@ -77,6 +77,11 @@ class MasqueradeView(View): to CourseMasquerade objects. """ course_key = CourseKey.from_string(course_key_string) + is_staff = has_staff_roles(request.user, course_key) + if not is_staff: + return JsonResponse({ + 'success': False, + }) masquerade_settings = request.session.get(MASQUERADE_SETTINGS_KEY, {}) request_json = request.json role = request_json.get('role', 'student')