|
6 | 6 | import edx_api_doc_tools as apidocs |
7 | 7 | from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication |
8 | 8 | from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser |
| 9 | +from opaque_keys import InvalidKeyError |
| 10 | +from opaque_keys.edx.locator import LibraryLocatorV2 |
| 11 | +from rest_framework import status |
| 12 | +from rest_framework.exceptions import ParseError |
| 13 | +from rest_framework.mixins import ListModelMixin |
9 | 14 | from rest_framework.permissions import IsAdminUser |
10 | 15 | from rest_framework.response import Response |
11 | | -from rest_framework import status |
| 16 | +from rest_framework.viewsets import GenericViewSet |
12 | 17 | from user_tasks.models import UserTaskStatus |
13 | 18 | from user_tasks.views import StatusViewSet |
14 | 19 |
|
15 | | -from cms.djangoapps.modulestore_migrator.api import start_migration_to_library, start_bulk_migration_to_library |
| 20 | +from cms.djangoapps.modulestore_migrator.api import start_bulk_migration_to_library, start_migration_to_library |
| 21 | +from openedx.core.djangoapps.content.course_overviews.models import CourseOverview |
| 22 | +from openedx.core.djangoapps.content_libraries import api as lib_api |
16 | 23 | from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser |
17 | 24 |
|
| 25 | +from ...models import ModulestoreMigration |
18 | 26 | from .serializers import ( |
19 | | - StatusWithModulestoreMigrationsSerializer, |
20 | | - ModulestoreMigrationSerializer, |
21 | 27 | BulkModulestoreMigrationSerializer, |
| 28 | + LibraryMigrationCourseSerializer, |
| 29 | + ModulestoreMigrationSerializer, |
| 30 | + StatusWithModulestoreMigrationsSerializer, |
22 | 31 | ) |
23 | 32 |
|
24 | | - |
25 | 33 | log = logging.getLogger(__name__) |
26 | 34 |
|
27 | 35 |
|
@@ -328,3 +336,55 @@ def cancel(self, request, *args, **kwargs): |
328 | 336 | We disable this endpoint to avoid confusion. |
329 | 337 | """ |
330 | 338 | raise NotImplementedError |
| 339 | + |
| 340 | + |
| 341 | +@apidocs.schema_for( |
| 342 | + "list", |
| 343 | + "List all course migrations to a library.", |
| 344 | + responses={ |
| 345 | + 201: LibraryMigrationCourseSerializer, |
| 346 | + 401: "The requester is not authenticated.", |
| 347 | + 403: "The requester does not have permission to access the library.", |
| 348 | + }, |
| 349 | +) |
| 350 | +class LibraryCourseMigrationViewSet(GenericViewSet, ListModelMixin): |
| 351 | + """ |
| 352 | + Show infomation about migrations related to a destination library. |
| 353 | + """ |
| 354 | + |
| 355 | + serializer_class = LibraryMigrationCourseSerializer |
| 356 | + pagination_class = None |
| 357 | + queryset = ModulestoreMigration.objects.all().select_related('target_collection', 'target', 'task_status') |
| 358 | + |
| 359 | + def get_serializer_context(self): |
| 360 | + """ |
| 361 | + Add course name list to the serializer context. |
| 362 | +
|
| 363 | + We need to display the course names in the migration view, and we get all of |
| 364 | + them here to avoid futher queries. |
| 365 | + """ |
| 366 | + context = super().get_serializer_context() |
| 367 | + queryset = self.get_queryset() |
| 368 | + course_keys = queryset.values_list('source__key', flat=True) |
| 369 | + courses = CourseOverview.get_all_courses(course_keys=course_keys) |
| 370 | + context['course_names'] = dict((str(course.id), course.display_name) for course in courses) |
| 371 | + return context |
| 372 | + |
| 373 | + def get_queryset(self): |
| 374 | + """ |
| 375 | + Override the default queryset to filter by the library key and check permissions. |
| 376 | + """ |
| 377 | + queryset = super().get_queryset() |
| 378 | + lib_key_str = self.kwargs['lib_key_str'] |
| 379 | + try: |
| 380 | + library_key = LibraryLocatorV2.from_string(lib_key_str) |
| 381 | + except InvalidKeyError as exc: |
| 382 | + raise ParseError(detail=f"Malformed library key: {lib_key_str}") from exc |
| 383 | + lib_api.require_permission_for_library_key( |
| 384 | + library_key, |
| 385 | + self.request.user, |
| 386 | + lib_api.permissions.CAN_VIEW_THIS_CONTENT_LIBRARY |
| 387 | + ) |
| 388 | + queryset = queryset.filter(target__key=library_key, source__key__startswith='course-v1') |
| 389 | + |
| 390 | + return queryset |
0 commit comments