Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(palm)!: backport instructor APIs conversion to DRF #702

Draft
wants to merge 6 commits into
base: opencraft-release/palm.1
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion lms/djangoapps/instructor/permissions.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""
Permissions for the instructor dashboard and associated actions
"""

from bridgekeeper import perms
from bridgekeeper.rules import is_staff
from opaque_keys.edx.keys import CourseKey
from rest_framework.permissions import BasePermission

from lms.djangoapps.courseware.rules import HasAccessRule, HasRolesRule
from openedx.core.lib.courses import get_course_by_id

ALLOW_STUDENT_TO_BYPASS_ENTRANCE_EXAM = 'instructor.allow_student_to_bypass_entrance_exam'
ASSIGN_TO_COHORTS = 'instructor.assign_to_cohorts'
Expand Down Expand Up @@ -79,3 +81,11 @@
) | HasAccessRule('staff') | HasAccessRule('instructor')
perms[VIEW_ENROLLMENTS] = HasAccessRule('staff')
perms[VIEW_FORUM_MEMBERS] = HasAccessRule('staff')


class InstructorPermission(BasePermission):
"""Generic permissions"""
def has_permission(self, request, view):
course = get_course_by_id(CourseKey.from_string(view.kwargs.get('course_id')))
permission = getattr(view, 'permission_name', None)
return request.user.has_perm(permission, course)
51 changes: 50 additions & 1 deletion lms/djangoapps/instructor/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2927,7 +2927,37 @@ def test_get_student_progress_url(self):
response = self.client.post(url, data)
assert response.status_code == 200
res_json = json.loads(response.content.decode('utf-8'))
assert 'progress_url' in res_json
expected_data = {
'course_id': str(self.course.id),
'progress_url': f'/courses/{self.course.id}/progress/{self.students[0].id}/'
}

for key, value in expected_data.items():
self.assertIn(key, res_json)
self.assertEqual(res_json[key], value)

def test_get_student_progress_url_response_headers(self):
"""
Test that the progress_url endpoint returns the correct headers.
"""
url = reverse('get_student_progress_url', kwargs={'course_id': str(self.course.id)})
data = {'unique_student_identifier': self.students[0].email}
response = self.client.post(url, data)
assert response.status_code == 200

expected_headers = {
'Allow': 'POST, OPTIONS', # drf view brings this key.
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Content-Language': 'en',
'Content-Length': str(len(response.content.decode('utf-8'))),
'Content-Type': 'application/json',
'Vary': 'Cookie, Accept-Language, origin',
'X-Frame-Options': 'DENY'
}

for key, value in expected_headers.items():
self.assertIn(key, response.headers)
self.assertEqual(response.headers[key], value)

def test_get_student_progress_url_from_uname(self):
""" Test that progress_url is in the successful response. """
Expand All @@ -2937,6 +2967,14 @@ def test_get_student_progress_url_from_uname(self):
assert response.status_code == 200
res_json = json.loads(response.content.decode('utf-8'))
assert 'progress_url' in res_json
expected_data = {
'course_id': str(self.course.id),
'progress_url': f'/courses/{self.course.id}/progress/{self.students[0].id}/'
}

for key, value in expected_data.items():
self.assertIn(key, res_json)
self.assertEqual(res_json[key], value)

def test_get_student_progress_url_noparams(self):
""" Test that the endpoint 404's without the required query params. """
Expand All @@ -2950,6 +2988,17 @@ def test_get_student_progress_url_nostudent(self):
response = self.client.post(url)
assert response.status_code == 400

def test_get_student_progress_url_without_permissions(self):
""" Test that progress_url returns 403 without credentials. """

# removed both roles from courses for instructor
CourseDataResearcherRole(self.course.id).remove_users(self.instructor)
CourseInstructorRole(self.course.id).remove_users(self.instructor)
url = reverse('get_student_progress_url', kwargs={'course_id': str(self.course.id)})
data = {'unique_student_identifier': self.students[0].email}
response = self.client.post(url, data)
assert response.status_code == 403


class TestInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
"""
Expand Down
Loading
Loading