Skip to content

Commit 4208e9d

Browse files
committed
feat: New Authz checks on import and export endpoints
1 parent 27f1365 commit 4208e9d

7 files changed

Lines changed: 438 additions & 18 deletions

File tree

cms/djangoapps/contentstore/api/tests/base.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class BaseCourseViewTest(SharedModuleStoreTestCase, APITestCase):
1818
Base test class for course data views.
1919
"""
2020
view_name = None # The name of the view to use in reverse() call in self.get_url()
21+
course_key_arg_name = 'course_id'
22+
extra_request_args = {}
2123

2224
@classmethod
2325
def setUpClass(cls):
@@ -86,9 +88,10 @@ def get_url(self, course_id):
8688
"""
8789
Helper function to create the url
8890
"""
91+
args = {
92+
self.course_key_arg_name: course_id,
93+
}
8994
return reverse(
9095
self.view_name,
91-
kwargs={
92-
'course_id': course_id
93-
}
96+
kwargs= args | self.extra_request_args
9497
)

cms/djangoapps/contentstore/views/import_export.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import re
1212
import shutil
1313
from wsgiref.util import FileWrapper
14+
from openedx_authz.constants.permissions import COURSES_EXPORT_COURSE, COURSES_IMPORT_COURSE
1415

1516
from django.conf import settings
1617
from django.contrib.auth.decorators import login_required
@@ -32,8 +33,9 @@
3233
from user_tasks.conf import settings as user_tasks_settings
3334
from user_tasks.models import UserTaskArtifact, UserTaskStatus
3435

36+
from openedx.core.djangoapps.authz.constants import LegacyAuthoringPermission
37+
from openedx.core.djangoapps.authz.decorators import user_has_course_permission
3538
from common.djangoapps.edxmako.shortcuts import render_to_response
36-
from common.djangoapps.student.auth import has_course_author_access
3739
from common.djangoapps.util.json_request import JsonResponse
3840
from common.djangoapps.util.monitoring import monitor_import_failure
3941
from common.djangoapps.util.views import ensure_valid_course_key
@@ -87,7 +89,12 @@ def import_handler(request, course_key_string):
8789
successful_url = reverse_course_url('course_handler', courselike_key)
8890
context_name = 'context_course'
8991
courselike_block = modulestore().get_course(courselike_key)
90-
if not has_course_author_access(request.user, courselike_key):
92+
if not user_has_course_permission(
93+
user=request.user,
94+
authz_permission=COURSES_IMPORT_COURSE.identifier,
95+
course_key=courselike_key,
96+
legacy_permission=LegacyAuthoringPermission.WRITE
97+
):
9198
raise PermissionDenied()
9299

93100
if 'application/json' in request.META.get('HTTP_ACCEPT', 'application/json'):
@@ -257,7 +264,12 @@ def import_status_handler(request, course_key_string, filename=None):
257264
258265
"""
259266
course_key = CourseKey.from_string(course_key_string)
260-
if not has_course_author_access(request.user, course_key):
267+
if not user_has_course_permission(
268+
user=request.user,
269+
authz_permission=COURSES_IMPORT_COURSE.identifier,
270+
course_key=course_key,
271+
legacy_permission=LegacyAuthoringPermission.WRITE
272+
):
261273
raise PermissionDenied()
262274

263275
# The task status record is authoritative once it's been created
@@ -318,7 +330,12 @@ def export_handler(request, course_key_string):
318330
a link appearing on the page once it's ready.
319331
"""
320332
course_key = CourseKey.from_string(course_key_string)
321-
if not has_course_author_access(request.user, course_key):
333+
if not user_has_course_permission(
334+
user=request.user,
335+
authz_permission=COURSES_EXPORT_COURSE.identifier,
336+
course_key=course_key,
337+
legacy_permission=LegacyAuthoringPermission.WRITE
338+
):
322339
raise PermissionDenied()
323340
library = isinstance(course_key, LibraryLocator)
324341
if library:
@@ -373,7 +390,12 @@ def export_status_handler(request, course_key_string):
373390
returned.
374391
"""
375392
course_key = CourseKey.from_string(course_key_string)
376-
if not has_course_author_access(request.user, course_key):
393+
if not user_has_course_permission(
394+
user=request.user,
395+
authz_permission=COURSES_EXPORT_COURSE.identifier,
396+
course_key=course_key,
397+
legacy_permission=LegacyAuthoringPermission.WRITE
398+
):
377399
raise PermissionDenied()
378400

379401
# The task status record is authoritative once it's been created
@@ -435,7 +457,12 @@ def export_output_handler(request, course_key_string):
435457
filesystem instead of an external service like S3.
436458
"""
437459
course_key = CourseKey.from_string(course_key_string)
438-
if not has_course_author_access(request.user, course_key):
460+
if not user_has_course_permission(
461+
user=request.user,
462+
authz_permission=COURSES_EXPORT_COURSE.identifier,
463+
course_key=course_key,
464+
legacy_permission=LegacyAuthoringPermission.WRITE
465+
):
439466
raise PermissionDenied()
440467

441468
task_status = _latest_task_status(request, course_key_string, export_output_handler)

0 commit comments

Comments
 (0)