def export(request, course_key_string): """ Trigger the async export job https://github.com/edx/edx-platform/blob/open-release/juniper.master/cms/djangoapps/contentstore/views/import_export.py#L290 POST /sn-api/courses/<course_key>/export/ """ course_key = CourseKey.from_string(course_key_string) if isinstance(course_key, LibraryLocator): courselike_module = modulestore().get_library(course_key) context = { 'context_library': courselike_module, 'courselike_home_url': reverse_library_url("library_handler", course_key), 'library': True } else: courselike_module = modulestore().get_course(course_key) if courselike_module is None: raise Http404 context = { 'context_course': courselike_module, 'courselike_home_url': reverse_course_url("course_handler", course_key), 'library': False } context['status_url'] = reverse_course_url('export_status_handler', course_key) export_olx.delay(request.user.id, course_key_string, request.LANGUAGE_CODE) return Response({'ExportStatus': 1})
def export_handler(request, course_key_string): """ The restful handler for exporting a course. GET html: return html page for import page json: not supported POST Start a Celery task to export the course The Studio UI uses a POST request to start the export asynchronously, with a link appearing on the page once it's ready. """ course_key = CourseKey.from_string(course_key_string) if not has_course_author_access(request.user, course_key): raise PermissionDenied() if isinstance(course_key, LibraryLocator): courselike_module = modulestore().get_library(course_key) context = { 'context_library': courselike_module, 'courselike_home_url': reverse_library_url("library_handler", course_key), 'library': True } else: courselike_module = modulestore().get_course(course_key) if courselike_module is None: raise Http404 context = { 'context_course': courselike_module, 'courselike_home_url': reverse_course_url("course_handler", course_key), 'library': False } context['status_url'] = reverse_course_url('export_status_handler', course_key) # an _accept URL parameter will be preferred over HTTP_ACCEPT in the header. requested_format = request.GET.get( '_accept', request.META.get('HTTP_ACCEPT', 'text/html')) if request.method == 'POST': export_olx.delay(request.user.id, course_key_string, request.LANGUAGE_CODE) return JsonResponse({'ExportStatus': 1}) elif 'text/html' in requested_format: return render_to_response('export.html', context) else: # Only HTML request format is supported (no JSON). return HttpResponse(status=406)
def test_exception(self, mock_export): # pylint: disable=unused-argument """ The export task should fail gracefully if an exception is thrown """ key = str(self.course.location.course_key) result = export_olx.delay(self.user.id, key, u'en') self._assert_failed(result, json.dumps({u'raw_error_msg': u'Boom!'}))
def test_exception(self, mock_export): # pylint: disable=unused-argument """ The export task should fail gracefully if an exception is thrown """ key = str(self.course.location.course_key) result = export_olx.delay(self.user.id, key, u'en') self._assert_failed(result, json.dumps({u'raw_error_msg': u'Boom!'}))
def export_handler(request, course_key_string): """ The restful handler for exporting a course. GET html: return html page for import page json: not supported POST Start a Celery task to export the course The Studio UI uses a POST request to start the export asynchronously, with a link appearing on the page once it's ready. """ course_key = CourseKey.from_string(course_key_string) if not has_course_author_access(request.user, course_key): raise PermissionDenied() if isinstance(course_key, LibraryLocator): courselike_module = modulestore().get_library(course_key) context = { 'context_library': courselike_module, 'courselike_home_url': reverse_library_url("library_handler", course_key), 'library': True } else: courselike_module = modulestore().get_course(course_key) if courselike_module is None: raise Http404 context = { 'context_course': courselike_module, 'courselike_home_url': reverse_course_url("course_handler", course_key), 'library': False } context['status_url'] = reverse_course_url('export_status_handler', course_key) # an _accept URL parameter will be preferred over HTTP_ACCEPT in the header. requested_format = request.GET.get('_accept', request.META.get('HTTP_ACCEPT', 'text/html')) if request.method == 'POST': export_olx.delay(request.user.id, course_key_string, request.LANGUAGE_CODE) return JsonResponse({'ExportStatus': 1}) elif 'text/html' in requested_format: return render_to_response('export.html', context) else: # Only HTML request format is supported (no JSON). return HttpResponse(status=406)
def test_non_course_author(self): """ Verify that users who aren't authors of the course are unable to export it """ _, nonstaff_user = self.create_non_staff_authed_user_client() key = str(self.course.location.course_key) result = export_olx.delay(nonstaff_user.id, key, u'en') self._assert_failed(result, u'Permission denied')
def test_invalid_user_id(self): """ Verify that attempts to export a course as an invalid user fail """ user_id = User.objects.order_by(u'-id').first().pk + 100 key = str(self.course.location.course_key) result = export_olx.delay(user_id, key, u'en') self._assert_failed(result, u'Unknown User ID: {}'.format(user_id))
def test_non_course_author(self): """ Verify that users who aren't authors of the course are unable to export it """ _, nonstaff_user = self.create_non_staff_authed_user_client() key = str(self.course.location.course_key) result = export_olx.delay(nonstaff_user.id, key, u'en') self._assert_failed(result, u'Permission denied')
def test_invalid_user_id(self): """ Verify that attempts to export a course as an invalid user fail """ user_id = User.objects.order_by(u'-id').first().pk + 100 key = str(self.course.location.course_key) result = export_olx.delay(user_id, key, u'en') self._assert_failed(result, u'Unknown User ID: {}'.format(user_id))
def test_success(self): """ Verify that a routine library export task succeeds """ key = str(self.lib_key) result = export_olx.delay(self.user.id, key, u'en') # pylint: disable=no-member status = UserTaskStatus.objects.get(task_id=result.id) self.assertEqual(status.state, UserTaskStatus.SUCCEEDED) artifacts = UserTaskArtifact.objects.filter(status=status) self.assertEqual(len(artifacts), 1) output = artifacts[0] self.assertEqual(output.name, 'Output')
def test_success(self): """ Verify that a routine course export task succeeds """ key = str(self.course.location.course_key) result = export_olx.delay(self.user.id, key, u'en') status = UserTaskStatus.objects.get(task_id=result.id) self.assertEqual(status.state, UserTaskStatus.SUCCEEDED) artifacts = UserTaskArtifact.objects.filter(status=status) self.assertEqual(len(artifacts), 1) output = artifacts[0] self.assertEqual(output.name, 'Output')
def test_success(self): """ Verify that a routine course export task succeeds """ key = str(self.course.location.course_key) result = export_olx.delay(self.user.id, key, u'en') status = UserTaskStatus.objects.get(task_id=result.id) self.assertEqual(status.state, UserTaskStatus.SUCCEEDED) artifacts = UserTaskArtifact.objects.filter(status=status) self.assertEqual(len(artifacts), 1) output = artifacts[0] self.assertEqual(output.name, 'Output')
def test_success(self): """ Verify that a routine library export task succeeds """ key = str(self.lib_key) result = export_olx.delay(self.user.id, key, u'en') # pylint: disable=no-member status = UserTaskStatus.objects.get(task_id=result.id) self.assertEqual(status.state, UserTaskStatus.SUCCEEDED) artifacts = UserTaskArtifact.objects.filter(status=status) self.assertEqual(len(artifacts), 1) output = artifacts[0] self.assertEqual(output.name, 'Output')
def export_handler(request, course_key_string): """ The restful handler for exporting a course. GET html: return html page for import page application/x-tgz: return tar.gz file containing exported course json: not supported POST Start a Celery task to export the course Note that there are 3 ways to request the tar.gz file. The Studio UI uses a POST request to start the export asynchronously, with a link appearing on the page once it's ready. Additionally, for backwards compatibility reasons the request header can specify application/x-tgz via HTTP_ACCEPT, or a query parameter can be used (?_accept=application/x-tgz); this will export the course synchronously and return the resulting file (unless the request times out for a large course). If the tar.gz file has been requested but the export operation fails, the import page will be returned including a description of the error. """ course_key = CourseKey.from_string(course_key_string) if not has_course_author_access(request.user, course_key): raise PermissionDenied() if isinstance(course_key, LibraryLocator): courselike_module = modulestore().get_library(course_key) context = { 'context_library': courselike_module, 'courselike_home_url': reverse_library_url("library_handler", course_key), 'library': True } else: courselike_module = modulestore().get_course(course_key) if courselike_module is None: raise Http404 context = { 'context_course': courselike_module, 'courselike_home_url': reverse_course_url("course_handler", course_key), 'library': False } context['status_url'] = reverse_course_url('export_status_handler', course_key) # an _accept URL parameter will be preferred over HTTP_ACCEPT in the header. requested_format = request.GET.get( '_accept', request.META.get('HTTP_ACCEPT', 'text/html')) if request.method == 'POST': export_olx.delay(request.user.id, course_key_string, request.LANGUAGE_CODE) return JsonResponse({'ExportStatus': 1}) elif 'application/x-tgz' in requested_format: try: tarball = create_export_tarball(courselike_module, course_key, context) return send_tarball(tarball) except SerializationError: return render_to_response('export.html', context) elif 'text/html' in requested_format: return render_to_response('export.html', context) else: # Only HTML or x-tgz request formats are supported (no JSON). return HttpResponse(status=406)
def export_handler(request, course_key_string): """ The restful handler for exporting a course. GET html: return html page for import page application/x-tgz: return tar.gz file containing exported course json: not supported POST Start a Celery task to export the course Note that there are 3 ways to request the tar.gz file. The Studio UI uses a POST request to start the export asynchronously, with a link appearing on the page once it's ready. Additionally, for backwards compatibility reasons the request header can specify application/x-tgz via HTTP_ACCEPT, or a query parameter can be used (?_accept=application/x-tgz); this will export the course synchronously and return the resulting file (unless the request times out for a large course). If the tar.gz file has been requested but the export operation fails, the import page will be returned including a description of the error. """ course_key = CourseKey.from_string(course_key_string) if not has_course_author_access(request.user, course_key): raise PermissionDenied() if isinstance(course_key, LibraryLocator): courselike_module = modulestore().get_library(course_key) context = { 'context_library': courselike_module, 'courselike_home_url': reverse_library_url("library_handler", course_key), 'library': True } else: courselike_module = modulestore().get_course(course_key) if courselike_module is None: raise Http404 context = { 'context_course': courselike_module, 'courselike_home_url': reverse_course_url("course_handler", course_key), 'library': False } context['status_url'] = reverse_course_url('export_status_handler', course_key) # an _accept URL parameter will be preferred over HTTP_ACCEPT in the header. requested_format = request.GET.get('_accept', request.META.get('HTTP_ACCEPT', 'text/html')) if request.method == 'POST': export_olx.delay(request.user.id, course_key_string, request.LANGUAGE_CODE) return JsonResponse({'ExportStatus': 1}) elif 'application/x-tgz' in requested_format: try: tarball = create_export_tarball(courselike_module, course_key, context) return send_tarball(tarball) except SerializationError: return render_to_response('export.html', context) elif 'text/html' in requested_format: return render_to_response('export.html', context) else: # Only HTML or x-tgz request formats are supported (no JSON). return HttpResponse(status=406)