diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/__init__.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/__init__.py index c60d33bc44..a5c3497998 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/serializers/__init__.py +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/__init__.py @@ -13,3 +13,7 @@ from .proctoring import ( ProctoringErrorsSerializer ) from .settings import CourseSettingsSerializer +from .xblock import XblockSerializer +from .videos import VideoUploadSerializer, VideoImageSerializer +from .transcripts import TranscriptSerializer +from .assets import AssetSerializer diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/assets.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/assets.py new file mode 100644 index 0000000000..e44c31b511 --- /dev/null +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/assets.py @@ -0,0 +1,13 @@ +""" +API Serializers for assets +""" +from rest_framework import serializers +from .common import StrictSerializer + + +class AssetSerializer(StrictSerializer): + """ + Strict Serializer for file assets. + """ + file = serializers.FileField(required=False, allow_null=True) + locked = serializers.BooleanField(required=False, allow_null=True) diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/common.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/common.py index bc2f8d2da6..362504ccb0 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/serializers/common.py +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/common.py @@ -17,3 +17,36 @@ class CourseCommonSerializer(serializers.Serializer): rerun_link = serializers.CharField() run = serializers.CharField() url = serializers.CharField() + + +class StrictSerializer(serializers.Serializer): + """ + Serializers that validates strong parameters, i.e. that no extra fields are passed in. + The serializer inheriting from this may throw a ValidationError and can be called in a try/catch + block that will return a 400 response on ValidationError. + """ + def to_internal_value(self, data): + """ + raise validation error if there are any unexpected fields. + """ + # Transform and validate the expected fields + ret = super().to_internal_value(data) + + # Get the list of valid fields from the serializer + valid_fields = set(self.fields.keys()) + + # Check for unexpected fields + extra_fields = set(data.keys()) - valid_fields + if extra_fields: + # Check if these unexpected fields are due to nested serializers + for field_name in list(extra_fields): + if isinstance(self.fields.get(field_name), serializers.BaseSerializer): + extra_fields.remove(field_name) + + # If there are still unexpected fields left, raise an error + if extra_fields: + raise serializers.ValidationError( + {field: ["This field is not expected."] for field in extra_fields} + ) + + return ret diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/transcripts.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/transcripts.py new file mode 100644 index 0000000000..2b72f1ff44 --- /dev/null +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/transcripts.py @@ -0,0 +1,15 @@ +""" +API Serializers for transcripts +""" +from rest_framework import serializers +from .common import StrictSerializer + + +class TranscriptSerializer(StrictSerializer): + """ + Strict Serializer for video transcripts. + """ + file = serializers.FileField() + edx_video_id = serializers.CharField() + language_code = serializers.CharField(required=False, allow_null=True) + new_language_code = serializers.CharField(required=False, allow_null=True) diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/videos.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/videos.py new file mode 100644 index 0000000000..c08856d1b5 --- /dev/null +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/videos.py @@ -0,0 +1,29 @@ +""" +API Serializers for videos +""" +from rest_framework import serializers +from .common import StrictSerializer + + +class FileSpecSerializer(StrictSerializer): + """ Strict Serializer for file specs """ + file_name = serializers.CharField() + content_type = serializers.ChoiceField(choices=['video/mp4', 'video/webm', 'video/ogg']) + + +class VideoUploadSerializer(StrictSerializer): + """ + Strict Serializer for video upload urls. + Note that these are not actually video uploads but endpoints to generate an upload url for AWS + and generating a video placeholder without performing an actual upload. + """ + files = serializers.ListField( + child=FileSpecSerializer() + ) + + +class VideoImageSerializer(StrictSerializer): + """ + Strict Serializer for video imgage files. + """ + file = serializers.ImageField() diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/xblock.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/xblock.py index 68d44af0ff..522a34e077 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/serializers/xblock.py +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/xblock.py @@ -1,15 +1,79 @@ """ API Serializers for xblocks """ +from rest_framework import serializers +from .common import StrictSerializer + +# The XblockSerializer is designed to be scalable and generic. As such, its structure +# should remain as general as possible. Avoid indiscriminately adding fields to it, +# especially those that are xblock-specific. In the future, we aim to develop a solution +# that can generate serializer fields dynamically based on the xblock definitions. -# TODO: implement and use serializer -# from rest_framework import serializers +class XblockSerializer(StrictSerializer): + """ + A serializer for xblocks that enforces strict validation. -# class XblockSerializer(serializers.Serializer): -# """Serializer for xblocks""" -# id=serializers.CharField(required=False) -# display_name=serializers.CharField(required=False) -# category=serializers.CharField(required=False) -# data=serializers.CharField(required=False) -# metadata=serializers.DictField(required=False) + The serializer ensures: + 1. All top-level fields have the expected data types. + 2. No unexpected fields are passed in. + + Note: The current list of fields is not exhaustive. It is primarily designed + to support the CMS API demo. While optional fields have been added, they were + chosen based on ease of discovery, not comprehensiveness. + """ + id = serializers.CharField(required=False, allow_null=True) + parent_locator = serializers.CharField(required=False, allow_null=True) + display_name = serializers.CharField(required=False, allow_null=True) + category = serializers.CharField(required=False, allow_null=True) + data = serializers.CharField(required=False, allow_null=True) + metadata = serializers.DictField(required=False, allow_null=True) + has_changes = serializers.BooleanField(required=False, allow_null=True) + children = serializers.ListField(required=False, allow_null=True) + fields = serializers.DictField(required=False, allow_null=True) + has_children = serializers.BooleanField(required=False, allow_null=True) + video_sharing_enabled = serializers.BooleanField(required=False, allow_null=True) + video_sharing_options = serializers.CharField(required=False, allow_null=True) + video_sharing_doc_url = serializers.CharField(required=False, allow_null=True) + edited_on = serializers.CharField(required=False, allow_null=True) + published = serializers.BooleanField(required=False, allow_null=True) + published_on = serializers.JSONField(required=False, allow_null=True) + studio_url = serializers.CharField(required=False, allow_null=True) + released_to_students = serializers.BooleanField(required=False, allow_null=True) + release_date = serializers.JSONField(required=False, allow_null=True) + nullout = serializers.JSONField(required=False, allow_null=True) + graderType = serializers.JSONField(required=False, allow_null=True) + visibility_state = serializers.CharField(required=False, allow_null=True) + has_explicit_staff_lock = serializers.BooleanField( + required=False, allow_null=True + ) + start = serializers.CharField(required=False, allow_null=True) + graded = serializers.BooleanField(required=False, allow_null=True) + due_date = serializers.CharField(required=False, allow_null=True) + due = serializers.JSONField(required=False, allow_null=True) + relative_weeks_due = serializers.JSONField(required=False, allow_null=True) + format = serializers.JSONField(required=False, allow_null=True) + course_graders = serializers.ListField(required=False, allow_null=True) + actions = serializers.DictField(required=False, allow_null=True) + explanatory_message = serializers.Field(required=False, allow_null=True) + group_access = serializers.DictField(required=False, allow_null=True) + user_partitions = serializers.ListField(required=False, allow_null=True) + show_correctness = serializers.CharField(required=False, allow_null=True) + discussion_enabled = serializers.BooleanField(required=False, allow_null=True) + ancestor_has_staff_lock = serializers.BooleanField(required=False, allow_null=True) + user_partition_info = serializers.DictField(required=False, allow_null=True) + summary_configuration_enabled = serializers.JSONField(required=False, allow_null=True) + isPrereq = serializers.BooleanField(required=False, allow_null=True) + prereqUsageKey = serializers.CharField(required=False, allow_null=True) + prereqMinScore = serializers.IntegerField(required=False, allow_null=True) + prereqMinCompletion = serializers.IntegerField(required=False, allow_null=True) + publish = serializers.ChoiceField( + required=False, + allow_null=True, + choices=['make_public', 'republish', 'discard_changes'] + ) + duplicate_source_locator = serializers.CharField(required=False, allow_null=True) + move_source_locator = serializers.CharField(required=False, allow_null=True) + target_index = serializers.IntegerField(required=False, allow_null=True) + boilerplate = serializers.JSONField(required=False, allow_null=True) + staged_content = serializers.CharField(required=False, allow_null=True) diff --git a/cms/djangoapps/contentstore/rest_api/v1/urls.py b/cms/djangoapps/contentstore/rest_api/v1/urls.py index 286424f5e1..9c1bef0c90 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/urls.py +++ b/cms/djangoapps/contentstore/rest_api/v1/urls.py @@ -74,7 +74,7 @@ urlpatterns = [ videos.VideosView.as_view(), name='studio_content_videos_uploads' ), re_path( - fr'^videos/images/{settings.COURSE_ID_PATTERN}/{VIDEO_ID_PATTERN}?$', + fr'^videos/images/{settings.COURSE_ID_PATTERN}/{VIDEO_ID_PATTERN}$', videos.VideoImagesView.as_view(), name='studio_content_videos_images' ), re_path( diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/assets.py b/cms/djangoapps/contentstore/rest_api/v1/views/assets.py index dc95087a12..481d850ca8 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/assets.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/assets.py @@ -14,6 +14,11 @@ from ....api import course_author_access_required from cms.djangoapps.contentstore.asset_storage_handlers import handle_assets import cms.djangoapps.contentstore.toggles as contentstore_toggles +from cms.djangoapps.contentstore.rest_api.v1.serializers import AssetSerializer +from .utils import validate_request_with_serializer +from rest_framework.parsers import (MultiPartParser, FormParser, JSONParser) +from openedx.core.lib.api.parsers import TypedFileUploadParser + log = logging.getLogger(__name__) toggles = contentstore_toggles @@ -25,6 +30,8 @@ class AssetsView(DeveloperErrorViewMixin, RetrieveUpdateDestroyAPIView, CreateAP course_key: required argument, needed to authorize course authors and identify the asset. asset_key_string: required argument, needed to identify the asset. """ + serializer_class = AssetSerializer + parser_classes = (JSONParser, MultiPartParser, FormParser, TypedFileUploadParser) def dispatch(self, request, *args, **kwargs): # TODO: probably want to refactor this to a decorator. @@ -44,11 +51,13 @@ class AssetsView(DeveloperErrorViewMixin, RetrieveUpdateDestroyAPIView, CreateAP @csrf_exempt @course_author_access_required + @validate_request_with_serializer def create(self, request, course_key): # pylint: disable=arguments-differ return handle_assets(request, course_key.html_id()) @course_author_access_required @expect_json_in_class_view + @validate_request_with_serializer def update(self, request, course_key, asset_key_string): # pylint: disable=arguments-differ return handle_assets(request, course_key.html_id(), asset_key_string) diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_assets.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_assets.py index 908af1d1bc..61fa331d6c 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_assets.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_assets.py @@ -6,9 +6,11 @@ not the underlying Xblock service. It checks that the assets_handler method of the Xblock service is called with the expected parameters. """ from unittest.mock import patch +from django.core.files import File from django.http import JsonResponse from django.urls import reverse +from mock import MagicMock from rest_framework import status from rest_framework.test import APITestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase @@ -17,6 +19,8 @@ from cms.djangoapps.contentstore.tests.test_utils import AuthorizeStaffTestCase ASSET_KEY_STRING = "asset-v1:dede+aba+weagi+type@asset+block@_0e37192a-42c4-441e-a3e1-8e40ec304e2e.jpg" +mock_image = MagicMock(file=File) +mock_image.name = "test.jpg" class AssetsViewTestCase(AuthorizeStaffTestCase): @@ -146,7 +150,7 @@ class AssetsViewPostTest(AssetsViewTestCase, ModuleStoreTestCase, APITestCase): def get_test_data(self): return { - "file": ASSET_KEY_STRING, + "file": mock_image, } def assert_assets_handler_called(self, *, mock_handle_assets, response): @@ -159,7 +163,7 @@ class AssetsViewPostTest(AssetsViewTestCase, ModuleStoreTestCase, APITestCase): course_id = self.get_course_key_string() - assert passed_args.data.get("file") == ASSET_KEY_STRING + assert passed_args.data.get("file").name == mock_image.name assert passed_args.method == "POST" assert passed_args.path == self.get_url() diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_xblock.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_xblock.py index f8d871a5be..64462a6ee2 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_xblock.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_xblock.py @@ -50,7 +50,7 @@ class XBlockViewTestCase(AuthorizeStaffTestCase): return_value=JsonResponse( { "locator": TEST_LOCATOR, - "courseKey": AuthorizeStaffTestCase.get_course_key_string(), + "course_key": AuthorizeStaffTestCase.get_course_key_string(), } ), ) @@ -128,7 +128,6 @@ class XBlockViewGetTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): assert response.status_code == status.HTTP_200_OK data = response.json() assert data["locator"] == TEST_LOCATOR - assert data["courseKey"] == self.get_course_key_string() class XBlockViewPostTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): @@ -150,7 +149,6 @@ class XBlockViewPostTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): return { "parent_locator": course_id, "category": "html", - "courseKey": course_id, } def assert_xblock_handler_called(self, *, mock_handle_xblock, response): @@ -161,9 +159,6 @@ class XBlockViewPostTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): mock_handle_xblock.assert_called_once() passed_args = mock_handle_xblock.call_args[0][0] - course_id = self.get_course_key_string() - - assert passed_args.data.get("courseKey") == course_id assert passed_args.method == "POST" assert passed_args.path == self.get_url() @@ -187,7 +182,6 @@ class XBlockViewPostTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): assert response.status_code == status.HTTP_200_OK data = response.json() assert data["locator"] == TEST_LOCATOR - assert data["courseKey"] == self.get_course_key_string() class XBlockViewPutTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): @@ -196,10 +190,8 @@ class XBlockViewPutTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): """ def get_test_data(self): - course_id = self.get_course_key_string() return { "category": "html", - "courseKey": course_id, "data": "

Updated block!

", "has_changes": True, "id": TEST_LOCATOR, @@ -216,9 +208,6 @@ class XBlockViewPutTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): mock_handle_xblock.assert_called_once() passed_args = mock_handle_xblock.call_args[0][0] - course_id = self.get_course_key_string() - - assert passed_args.data.get("courseKey") == course_id assert passed_args.data.get("data") == "

Updated block!

" assert passed_args.data.get("id") == TEST_LOCATOR assert passed_args.method == "PUT" @@ -244,7 +233,6 @@ class XBlockViewPutTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): assert response.status_code == status.HTTP_200_OK data = response.json() assert data["locator"] == TEST_LOCATOR - assert data["courseKey"] == self.get_course_key_string() class XBlockViewPatchTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): @@ -253,10 +241,8 @@ class XBlockViewPatchTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): """ def get_test_data(self): - course_id = self.get_course_key_string() return { "category": "html", - "courseKey": course_id, "data": "

Patched block!

", "has_changes": True, "id": TEST_LOCATOR, @@ -273,9 +259,6 @@ class XBlockViewPatchTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): mock_handle_xblock.assert_called_once() passed_args = mock_handle_xblock.call_args[0][0] - course_id = self.get_course_key_string() - - assert passed_args.data.get("courseKey") == course_id assert passed_args.data.get("data") == "

Patched block!

" assert passed_args.data.get("id") == TEST_LOCATOR assert passed_args.method == "PATCH" @@ -301,7 +284,6 @@ class XBlockViewPatchTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): assert response.status_code == status.HTTP_200_OK data = response.json() assert data["locator"] == TEST_LOCATOR - assert data["courseKey"] == self.get_course_key_string() class XBlockViewDeleteTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase): @@ -343,4 +325,3 @@ class XBlockViewDeleteTest(XBlockViewTestCase, ModuleStoreTestCase, APITestCase) assert response.status_code == status.HTTP_200_OK data = response.json() assert data["locator"] == TEST_LOCATOR - assert data["courseKey"] == self.get_course_key_string() diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/transcripts.py b/cms/djangoapps/contentstore/rest_api/v1/views/transcripts.py index e4e8ff8667..f621929f9c 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/transcripts.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/transcripts.py @@ -21,6 +21,11 @@ from cms.djangoapps.contentstore.transcript_storage_handlers import ( handle_transcript_download, ) import cms.djangoapps.contentstore.toggles as contentstore_toggles +from cms.djangoapps.contentstore.rest_api.v1.serializers import TranscriptSerializer +from rest_framework.parsers import (MultiPartParser, FormParser) +from openedx.core.lib.api.parsers import TypedFileUploadParser + +from .utils import validate_request_with_serializer log = logging.getLogger(__name__) toggles = contentstore_toggles @@ -34,6 +39,8 @@ class TranscriptView(DeveloperErrorViewMixin, CreateAPIView, RetrieveAPIView, De edx_video_id: optional query parameter, needed to identify the transcript. language_code: optional query parameter, needed to identify the transcript. """ + serializer_class = TranscriptSerializer + parser_classes = (MultiPartParser, FormParser, TypedFileUploadParser) def dispatch(self, request, *args, **kwargs): if not toggles.use_studio_content_api(): @@ -43,6 +50,7 @@ class TranscriptView(DeveloperErrorViewMixin, CreateAPIView, RetrieveAPIView, De @csrf_exempt @course_author_access_required @expect_json_in_class_view + @validate_request_with_serializer def create(self, request, course_key_string): # pylint: disable=arguments-differ return upload_transcript(request) diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/utils.py b/cms/djangoapps/contentstore/rest_api/v1/views/utils.py new file mode 100644 index 0000000000..7175b76c7c --- /dev/null +++ b/cms/djangoapps/contentstore/rest_api/v1/views/utils.py @@ -0,0 +1,23 @@ +""" +Utilities for the REST API views. +""" +from functools import wraps +from django.http import HttpResponseBadRequest + + +def validate_request_with_serializer(view_func): + """ + A decorator to validate request data using the view's serializer. + + Usage: + @validate_request_with_serializer + def my_view_function(self, request, ...): + ... + """ + @wraps(view_func) + def _wrapped_view(instance, request, *args, **kwargs): + serializer = instance.serializer_class(data=request.data) + if not serializer.is_valid(): + return HttpResponseBadRequest(reason=serializer.errors) + return view_func(instance, request, *args, **kwargs) + return _wrapped_view diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/videos.py b/cms/djangoapps/contentstore/rest_api/v1/views/videos.py index a6e776b77c..710dbb5df2 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/videos.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/videos.py @@ -7,10 +7,12 @@ from rest_framework.generics import ( RetrieveAPIView, DestroyAPIView ) +from rest_framework.parsers import (MultiPartParser, FormParser) from django.views.decorators.csrf import csrf_exempt from django.http import Http404 from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes +from openedx.core.lib.api.parsers import TypedFileUploadParser from common.djangoapps.util.json_request import expect_json_in_class_view from ....api import course_author_access_required @@ -19,10 +21,12 @@ from cms.djangoapps.contentstore.video_storage_handlers import ( handle_videos, get_video_encodings_download, handle_video_images, - enabled_video_features, - handle_generate_video_upload_link + enabled_video_features ) +from cms.djangoapps.contentstore.rest_api.v1.serializers import VideoUploadSerializer, VideoImageSerializer import cms.djangoapps.contentstore.toggles as contentstore_toggles +from .utils import validate_request_with_serializer + log = logging.getLogger(__name__) toggles = contentstore_toggles @@ -35,6 +39,7 @@ class VideosView(DeveloperErrorViewMixin, CreateAPIView, RetrieveAPIView, Destro course_key: required argument, needed to authorize course authors and identify the video. video_id: required argument, needed to identify the video. """ + serializer_class = VideoUploadSerializer def dispatch(self, request, *args, **kwargs): # TODO: probably want to refactor this to a decorator. @@ -50,7 +55,9 @@ class VideosView(DeveloperErrorViewMixin, CreateAPIView, RetrieveAPIView, Destro @csrf_exempt @course_author_access_required @expect_json_in_class_view + @validate_request_with_serializer def create(self, request, course_key): # pylint: disable=arguments-differ + """Deprecated. Use the upload_link endpoint instead.""" return handle_videos(request, course_key.html_id()) @course_author_access_required @@ -70,6 +77,8 @@ class VideoImagesView(DeveloperErrorViewMixin, CreateAPIView): course_key: required argument, needed to authorize course authors and identify the video. video_id: required argument, needed to identify the video. """ + serializer_class = VideoImageSerializer + parser_classes = (MultiPartParser, FormParser, TypedFileUploadParser) def dispatch(self, request, *args, **kwargs): # TODO: probably want to refactor this to a decorator. @@ -85,6 +94,7 @@ class VideoImagesView(DeveloperErrorViewMixin, CreateAPIView): @csrf_exempt @course_author_access_required @expect_json_in_class_view + @validate_request_with_serializer def create(self, request, course_key, edx_video_id=None): # pylint: disable=arguments-differ return handle_video_images(request, course_key.html_id(), edx_video_id) @@ -140,6 +150,7 @@ class UploadLinkView(DeveloperErrorViewMixin, CreateAPIView): """ public rest API endpoint providing a list of enabled video features. """ + serializer_class = VideoUploadSerializer def dispatch(self, request, *args, **kwargs): # TODO: probably want to refactor this to a decorator. @@ -155,5 +166,6 @@ class UploadLinkView(DeveloperErrorViewMixin, CreateAPIView): @csrf_exempt @course_author_access_required @expect_json_in_class_view + @validate_request_with_serializer def create(self, request, course_key): # pylint: disable=arguments-differ - return handle_generate_video_upload_link(request, course_key.html_id()) + return handle_videos(request, course_key.html_id()) diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/xblock.py b/cms/djangoapps/contentstore/rest_api/v1/views/xblock.py index 13087c6cd3..0e5765d8a2 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/xblock.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/xblock.py @@ -13,7 +13,8 @@ from cms.djangoapps.contentstore.api import course_author_access_required from cms.djangoapps.contentstore.xblock_storage_handlers import view_handlers import cms.djangoapps.contentstore.toggles as contentstore_toggles -# from cms.djangoapps.contentstore.rest_api.v1.serializers import XblockSerializer +from cms.djangoapps.contentstore.rest_api.v1.serializers import XblockSerializer +from .utils import validate_request_with_serializer log = logging.getLogger(__name__) @@ -29,8 +30,7 @@ class XblockView(DeveloperErrorViewMixin, RetrieveUpdateDestroyAPIView, CreateAP usage_key_string (optional): xblock identifier, for example in the form of "block-v1:+type@+block@" """ - # TODO: uncomment next line after XblockSerializer is implemented - # serializer_class = XblockSerializer + serializer_class = XblockSerializer def dispatch(self, request, *args, **kwargs): # TODO: probably want to refactor this to a decorator. @@ -51,11 +51,13 @@ class XblockView(DeveloperErrorViewMixin, RetrieveUpdateDestroyAPIView, CreateAP @course_author_access_required @expect_json_in_class_view + @validate_request_with_serializer def update(self, request, course_key, usage_key_string=None): return handle_xblock(request, usage_key_string) @course_author_access_required @expect_json_in_class_view + @validate_request_with_serializer def partial_update(self, request, course_key, usage_key_string=None): return handle_xblock(request, usage_key_string) @@ -67,5 +69,6 @@ class XblockView(DeveloperErrorViewMixin, RetrieveUpdateDestroyAPIView, CreateAP @csrf_exempt @course_author_access_required @expect_json_in_class_view + @validate_request_with_serializer def create(self, request, course_key, usage_key_string=None): return handle_xblock(request, usage_key_string) diff --git a/cms/djangoapps/contentstore/tests/test_video_utils.py b/cms/djangoapps/contentstore/tests/test_video_utils.py index 80d55b92b8..c81761a283 100644 --- a/cms/djangoapps/contentstore/tests/test_video_utils.py +++ b/cms/djangoapps/contentstore/tests/test_video_utils.py @@ -5,7 +5,7 @@ Unit tests for video utils. from datetime import datetime from unittest import TestCase -from unittest.mock import MagicMock, patch +from unittest import mock import ddt import pytz @@ -144,7 +144,7 @@ class ScrapeVideoThumbnailsTestCase(CourseTestCase): return mocked_response @override_settings(AWS_ACCESS_KEY_ID='test_key_id', AWS_SECRET_ACCESS_KEY='test_secret') - @patch('requests.get') + @mock.patch('requests.get') @ddt.data( ( { @@ -228,7 +228,7 @@ class ScrapeVideoThumbnailsTestCase(CourseTestCase): self.assertEqual(thumbnail_content_type, 'image/jpeg') @override_settings(AWS_ACCESS_KEY_ID='test_key_id', AWS_SECRET_ACCESS_KEY='test_secret') - @patch('requests.get') + @mock.patch('requests.get') def test_scrape_youtube_thumbnail(self, mocked_request): """ Test that youtube thumbnails are correctly scrapped. @@ -273,8 +273,8 @@ class ScrapeVideoThumbnailsTestCase(CourseTestCase): ) ) @override_settings(AWS_ACCESS_KEY_ID='test_key_id', AWS_SECRET_ACCESS_KEY='test_secret') - @patch('cms.djangoapps.contentstore.video_utils.LOGGER') - @patch('requests.get') + @mock.patch('cms.djangoapps.contentstore.video_utils.LOGGER') + @mock.patch('requests.get') @ddt.unpack def test_scrape_youtube_thumbnail_logging( self, @@ -333,8 +333,8 @@ class ScrapeVideoThumbnailsTestCase(CourseTestCase): ) ), ) - @patch('cms.djangoapps.contentstore.video_utils.LOGGER') - @patch('cms.djangoapps.contentstore.video_utils.download_youtube_video_thumbnail') + @mock.patch('cms.djangoapps.contentstore.video_utils.LOGGER') + @mock.patch('cms.djangoapps.contentstore.video_utils.download_youtube_video_thumbnail') @ddt.unpack def test_no_video_thumbnail_downloaded( self, @@ -376,7 +376,7 @@ class S3Boto3TestCase(TestCase): def setUp(self): self.storage = S3Boto3Storage() - self.storage._connections.connection = MagicMock() # pylint: disable=protected-access + self.storage._connections.connection = mock.MagicMock() # pylint: disable=protected-access def order_dict(self, dictionary): """ @@ -417,18 +417,18 @@ class S3Boto3TestCase(TestCase): content = ContentFile('new content') storage = S3Boto3Storage(**{'bucket_name': 'test'}) - storage._connections.connection = MagicMock() # pylint: disable=protected-access + storage._connections.connection = mock.MagicMock() # pylint: disable=protected-access storage.save(name, content) storage.bucket.Object.assert_called_once_with(name) obj = storage.bucket.Object.return_value obj.upload_fileobj.assert_called_with( - content, + mock.ANY, ExtraArgs=self.order_dict({ 'ContentType': 'text/plain', }), - Config=storage._transfer_config # pylint: disable=protected-access + Config=storage.transfer_config # pylint: disable=protected-access ) @override_settings(AWS_DEFAULT_ACL='public-read') @@ -445,7 +445,7 @@ class S3Boto3TestCase(TestCase): name = 'test_storage_save.txt' content = ContentFile('new content') storage = S3Boto3Storage(**{'bucket_name': 'test', 'default_acl': default_acl}) - storage._connections.connection = MagicMock() # pylint: disable=protected-access + storage._connections.connection = mock.MagicMock() # pylint: disable=protected-access storage.save(name, content) storage.bucket.Object.assert_called_once_with(name) @@ -461,9 +461,9 @@ class S3Boto3TestCase(TestCase): del ExtraArgs['ACL'] obj.upload_fileobj.assert_called_with( - content, + mock.ANY, ExtraArgs=self.order_dict(ExtraArgs), - Config=storage._transfer_config # pylint: disable=protected-access + Config=storage.transfer_config # pylint: disable=protected-access ) @ddt.data('public-read', 'private') @@ -476,16 +476,16 @@ class S3Boto3TestCase(TestCase): content = ContentFile('new content') storage = S3Boto3Storage(**{'bucket_name': 'test', 'default_acl': None}) - storage._connections.connection = MagicMock() # pylint: disable=protected-access + storage._connections.connection = mock.MagicMock() # pylint: disable=protected-access storage.save(name, content) storage.bucket.Object.assert_called_once_with(name) obj = storage.bucket.Object.return_value obj.upload_fileobj.assert_called_with( - content, - ExtraArgs=self.order_dict({ + mock.ANY, + Config=storage.transfer_config, # pylint: disable=protected-access + ExtraArgs={ 'ContentType': 'text/plain', - }), - Config=storage._transfer_config # pylint: disable=protected-access + }, ) diff --git a/cms/djangoapps/contentstore/video_storage_handlers.py b/cms/djangoapps/contentstore/video_storage_handlers.py index d1a7c55ac6..6e83a5b9e3 100644 --- a/cms/djangoapps/contentstore/video_storage_handlers.py +++ b/cms/djangoapps/contentstore/video_storage_handlers.py @@ -729,7 +729,9 @@ def videos_post(course, request): """ if use_mock_video_uploads(): - return {'files': [{'file_name': 'video.mp4', 'upload_url': 'http://example.com/put_video'}]}, 200 + return {'files': [{ + 'file_name': 'video.mp4', 'upload_url': 'http://example.com/put_video', 'edx_video_id': '1234' + }]}, 200 error = None data = request.json diff --git a/conf/locale/ca/LC_MESSAGES/django.po b/conf/locale/ca/LC_MESSAGES/django.po index 2b43475907..f3e40b6a47 100644 --- a/conf/locale/ca/LC_MESSAGES/django.po +++ b/conf/locale/ca/LC_MESSAGES/django.po @@ -67,7 +67,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Catalan (https://app.transifex.com/open-edx/teams/6205/ca/)\n" diff --git a/conf/locale/el/LC_MESSAGES/django.po b/conf/locale/el/LC_MESSAGES/django.po index 5797d4de82..6637c4de6f 100644 --- a/conf/locale/el/LC_MESSAGES/django.po +++ b/conf/locale/el/LC_MESSAGES/django.po @@ -98,7 +98,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Greek (https://app.transifex.com/open-edx/teams/6205/el/)\n" diff --git a/conf/locale/en/LC_MESSAGES/django.po b/conf/locale/en/LC_MESSAGES/django.po index e21204ea11..b746467a6a 100644 --- a/conf/locale/en/LC_MESSAGES/django.po +++ b/conf/locale/en/LC_MESSAGES/django.po @@ -38,8 +38,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-09-20 12:47+0000\n" -"PO-Revision-Date: 2023-09-20 12:47:19.650590\n" +"POT-Creation-Date: 2023-09-24 20:36+0000\n" +"PO-Revision-Date: 2023-09-24 20:36:20.303017\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "Language: en\n" @@ -6374,6 +6374,17 @@ msgstr "" msgid "Original usage key/ID of the thing that is in the clipboard." msgstr "" +#: openedx/core/djangoapps/content_tagging/models/base.py +#: wiki/models/article.py +msgid "owner" +msgstr "" + +#: openedx/core/djangoapps/content_tagging/models/base.py +msgid "" +"Organization that is related to this taxonomy.If None, then this taxonomy is" +" related to all organizations." +msgstr "" + #: openedx/core/djangoapps/cors_csrf/models.py msgid "" "List of domains that are allowed to make cross-domain requests to this site." @@ -8169,16 +8180,6 @@ msgid "" "to date." msgstr "" -#: openedx/features/content_tagging/models/base.py wiki/models/article.py -msgid "owner" -msgstr "" - -#: openedx/features/content_tagging/models/base.py -msgid "" -"Organization that is related to this taxonomy.If None, then this taxonomy is" -" related to all organizations." -msgstr "" - #: openedx/features/content_type_gating/models.py #: openedx/features/course_duration_limits/models.py #: lms/templates/support/feature_based_enrollments.html diff --git a/conf/locale/en/LC_MESSAGES/djangojs.po b/conf/locale/en/LC_MESSAGES/djangojs.po index 77cda03c1d..8c7acf64fb 100644 --- a/conf/locale/en/LC_MESSAGES/djangojs.po +++ b/conf/locale/en/LC_MESSAGES/djangojs.po @@ -32,8 +32,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-09-20 12:47+0000\n" -"PO-Revision-Date: 2023-09-20 12:47:19.757119\n" +"POT-Creation-Date: 2023-09-24 20:36+0000\n" +"PO-Revision-Date: 2023-09-24 20:36:20.294880\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "Language: en\n" diff --git a/conf/locale/eo/LC_MESSAGES/django.mo b/conf/locale/eo/LC_MESSAGES/django.mo index 3828753ce5..cd2f6b7303 100644 Binary files a/conf/locale/eo/LC_MESSAGES/django.mo and b/conf/locale/eo/LC_MESSAGES/django.mo differ diff --git a/conf/locale/eo/LC_MESSAGES/django.po b/conf/locale/eo/LC_MESSAGES/django.po index c092432ca6..459f71da15 100644 --- a/conf/locale/eo/LC_MESSAGES/django.po +++ b/conf/locale/eo/LC_MESSAGES/django.po @@ -38,8 +38,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-09-20 12:47+0000\n" -"PO-Revision-Date: 2023-09-20 12:47:19.650590\n" +"POT-Creation-Date: 2023-09-24 20:36+0000\n" +"PO-Revision-Date: 2023-09-24 20:36:20.303017\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "Language: eo\n" @@ -8051,6 +8051,19 @@ msgstr "" "Örïgïnäl üsägé kéý/ÌD öf thé thïng thät ïs ïn thé çlïpßöärd. Ⱡ'σяєм ιρѕυм " "∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#" +#: openedx/core/djangoapps/content_tagging/models/base.py +#: wiki/models/article.py +msgid "owner" +msgstr "öwnér Ⱡ'σяєм ιρѕ#" + +#: openedx/core/djangoapps/content_tagging/models/base.py +msgid "" +"Organization that is related to this taxonomy.If None, then this taxonomy is" +" related to all organizations." +msgstr "" +"Örgänïzätïön thät ïs rélätéd tö thïs täxönömý.Ìf Nöné, thén thïs täxönömý ïs" +" rélätéd tö äll örgänïzätïöns. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт #" + #: openedx/core/djangoapps/cors_csrf/models.py msgid "" "List of domains that are allowed to make cross-domain requests to this site." @@ -10427,18 +10440,6 @@ msgstr "" "Ýöü hävé süççéssfüllý shïftéd ýöür çöürsé sçhédülé änd ýöür çäléndär ïs üp " "tö däté. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" -#: openedx/features/content_tagging/models/base.py wiki/models/article.py -msgid "owner" -msgstr "öwnér Ⱡ'σяєм ιρѕ#" - -#: openedx/features/content_tagging/models/base.py -msgid "" -"Organization that is related to this taxonomy.If None, then this taxonomy is" -" related to all organizations." -msgstr "" -"Örgänïzätïön thät ïs rélätéd tö thïs täxönömý.Ìf Nöné, thén thïs täxönömý ïs" -" rélätéd tö äll örgänïzätïöns. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт #" - #: openedx/features/content_type_gating/models.py #: openedx/features/course_duration_limits/models.py #: lms/templates/support/feature_based_enrollments.html diff --git a/conf/locale/eo/LC_MESSAGES/djangojs.mo b/conf/locale/eo/LC_MESSAGES/djangojs.mo index 52cf0799ae..a037d84d76 100644 Binary files a/conf/locale/eo/LC_MESSAGES/djangojs.mo and b/conf/locale/eo/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/eo/LC_MESSAGES/djangojs.po b/conf/locale/eo/LC_MESSAGES/djangojs.po index 02a8aa07e8..981fb3c738 100644 --- a/conf/locale/eo/LC_MESSAGES/djangojs.po +++ b/conf/locale/eo/LC_MESSAGES/djangojs.po @@ -32,8 +32,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-09-20 12:47+0000\n" -"PO-Revision-Date: 2023-09-20 12:47:19.757119\n" +"POT-Creation-Date: 2023-09-24 20:36+0000\n" +"PO-Revision-Date: 2023-09-24 20:36:20.294880\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "Language: eo\n" diff --git a/conf/locale/eu_ES/LC_MESSAGES/django.po b/conf/locale/eu_ES/LC_MESSAGES/django.po index 47e35a42f4..022886794f 100644 --- a/conf/locale/eu_ES/LC_MESSAGES/django.po +++ b/conf/locale/eu_ES/LC_MESSAGES/django.po @@ -64,7 +64,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Abel Camacho , 2019\n" "Language-Team: Basque (Spain) (https://app.transifex.com/open-edx/teams/6205/eu_ES/)\n" diff --git a/conf/locale/fa_IR/LC_MESSAGES/djangojs.po b/conf/locale/fa_IR/LC_MESSAGES/djangojs.po index 9d884cfc63..24db4fbf75 100644 --- a/conf/locale/fa_IR/LC_MESSAGES/djangojs.po +++ b/conf/locale/fa_IR/LC_MESSAGES/djangojs.po @@ -88,7 +88,7 @@ msgid "" msgstr "" "Project-Id-Version: edx-platform\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:42+0000\n" +"POT-Creation-Date: 2023-09-17 20:42+0000\n" "PO-Revision-Date: 2014-06-11 15:18+0000\n" "Last-Translator: SeyedMahdi Saeid , 2023\n" "Language-Team: Persian (Iran) (http://app.transifex.com/open-edx/edx-platform/language/fa_IR/)\n" diff --git a/conf/locale/fr/LC_MESSAGES/django.po b/conf/locale/fr/LC_MESSAGES/django.po index 8db14d164e..4278151bbf 100644 --- a/conf/locale/fr/LC_MESSAGES/django.po +++ b/conf/locale/fr/LC_MESSAGES/django.po @@ -316,7 +316,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Alexandre DS , 2020\n" "Language-Team: French (https://app.transifex.com/open-edx/teams/6205/fr/)\n" diff --git a/conf/locale/id/LC_MESSAGES/django.po b/conf/locale/id/LC_MESSAGES/django.po index 8880340d3c..b83ecbae83 100644 --- a/conf/locale/id/LC_MESSAGES/django.po +++ b/conf/locale/id/LC_MESSAGES/django.po @@ -106,7 +106,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Aprisa Chrysantina , 2019\n" "Language-Team: Indonesian (https://app.transifex.com/open-edx/teams/6205/id/)\n" diff --git a/conf/locale/ja_JP/LC_MESSAGES/django.po b/conf/locale/ja_JP/LC_MESSAGES/django.po index 4fc3fc97fe..ed5767dc03 100644 --- a/conf/locale/ja_JP/LC_MESSAGES/django.po +++ b/conf/locale/ja_JP/LC_MESSAGES/django.po @@ -114,7 +114,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Japanese (Japan) (https://app.transifex.com/open-edx/teams/6205/ja_JP/)\n" diff --git a/conf/locale/ka/LC_MESSAGES/django.po b/conf/locale/ka/LC_MESSAGES/django.po index aae8d161cc..30851f8529 100644 --- a/conf/locale/ka/LC_MESSAGES/django.po +++ b/conf/locale/ka/LC_MESSAGES/django.po @@ -60,7 +60,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Georgian (https://app.transifex.com/open-edx/teams/6205/ka/)\n" diff --git a/conf/locale/lt_LT/LC_MESSAGES/django.po b/conf/locale/lt_LT/LC_MESSAGES/django.po index aa0f63df5f..feddb2b7f6 100644 --- a/conf/locale/lt_LT/LC_MESSAGES/django.po +++ b/conf/locale/lt_LT/LC_MESSAGES/django.po @@ -72,7 +72,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Lithuanian (Lithuania) (https://app.transifex.com/open-edx/teams/6205/lt_LT/)\n" diff --git a/conf/locale/lv/LC_MESSAGES/django.po b/conf/locale/lv/LC_MESSAGES/django.po index 34a05acee9..7975d7c8d1 100644 --- a/conf/locale/lv/LC_MESSAGES/django.po +++ b/conf/locale/lv/LC_MESSAGES/django.po @@ -49,7 +49,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Latvian (https://app.transifex.com/open-edx/teams/6205/lv/)\n" diff --git a/conf/locale/mn/LC_MESSAGES/django.po b/conf/locale/mn/LC_MESSAGES/django.po index caef90941c..e7ad5f189e 100644 --- a/conf/locale/mn/LC_MESSAGES/django.po +++ b/conf/locale/mn/LC_MESSAGES/django.po @@ -74,7 +74,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Mongolian (https://app.transifex.com/open-edx/teams/6205/mn/)\n" diff --git a/conf/locale/pl/LC_MESSAGES/django.po b/conf/locale/pl/LC_MESSAGES/django.po index 9ab2c97f82..63d7c1340e 100644 --- a/conf/locale/pl/LC_MESSAGES/django.po +++ b/conf/locale/pl/LC_MESSAGES/django.po @@ -150,7 +150,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Marcin Miłek, 2022\n" "Language-Team: Polish (https://app.transifex.com/open-edx/teams/6205/pl/)\n" diff --git a/conf/locale/rtl/LC_MESSAGES/django.mo b/conf/locale/rtl/LC_MESSAGES/django.mo index 8c8aec060c..3933c65090 100644 Binary files a/conf/locale/rtl/LC_MESSAGES/django.mo and b/conf/locale/rtl/LC_MESSAGES/django.mo differ diff --git a/conf/locale/rtl/LC_MESSAGES/django.po b/conf/locale/rtl/LC_MESSAGES/django.po index a078710c1d..1a218f7dc4 100644 --- a/conf/locale/rtl/LC_MESSAGES/django.po +++ b/conf/locale/rtl/LC_MESSAGES/django.po @@ -38,8 +38,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-09-20 12:47+0000\n" -"PO-Revision-Date: 2023-09-20 12:47:19.650590\n" +"POT-Creation-Date: 2023-09-24 20:36+0000\n" +"PO-Revision-Date: 2023-09-24 20:36:20.303017\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "Language: rtl\n" @@ -7007,6 +7007,19 @@ msgstr "" msgid "Original usage key/ID of the thing that is in the clipboard." msgstr "Øɹᴉƃᴉnɐl nsɐƃǝ ʞǝʎ/ƗĐ øɟ ʇɥǝ ʇɥᴉnƃ ʇɥɐʇ ᴉs ᴉn ʇɥǝ ɔlᴉdbøɐɹd." +#: openedx/core/djangoapps/content_tagging/models/base.py +#: wiki/models/article.py +msgid "owner" +msgstr "øʍnǝɹ" + +#: openedx/core/djangoapps/content_tagging/models/base.py +msgid "" +"Organization that is related to this taxonomy.If None, then this taxonomy is" +" related to all organizations." +msgstr "" +"Øɹƃɐnᴉzɐʇᴉøn ʇɥɐʇ ᴉs ɹǝlɐʇǝd ʇø ʇɥᴉs ʇɐxønøɯʎ.Ɨɟ Nønǝ, ʇɥǝn ʇɥᴉs ʇɐxønøɯʎ ᴉs" +" ɹǝlɐʇǝd ʇø ɐll øɹƃɐnᴉzɐʇᴉøns." + #: openedx/core/djangoapps/cors_csrf/models.py msgid "" "List of domains that are allowed to make cross-domain requests to this site." @@ -9018,18 +9031,6 @@ msgstr "" "Ɏøn ɥɐʌǝ snɔɔǝssɟnllʎ sɥᴉɟʇǝd ʎønɹ ɔønɹsǝ sɔɥǝdnlǝ ɐnd ʎønɹ ɔɐlǝndɐɹ ᴉs nd " "ʇø dɐʇǝ." -#: openedx/features/content_tagging/models/base.py wiki/models/article.py -msgid "owner" -msgstr "øʍnǝɹ" - -#: openedx/features/content_tagging/models/base.py -msgid "" -"Organization that is related to this taxonomy.If None, then this taxonomy is" -" related to all organizations." -msgstr "" -"Øɹƃɐnᴉzɐʇᴉøn ʇɥɐʇ ᴉs ɹǝlɐʇǝd ʇø ʇɥᴉs ʇɐxønøɯʎ.Ɨɟ Nønǝ, ʇɥǝn ʇɥᴉs ʇɐxønøɯʎ ᴉs" -" ɹǝlɐʇǝd ʇø ɐll øɹƃɐnᴉzɐʇᴉøns." - #: openedx/features/content_type_gating/models.py #: openedx/features/course_duration_limits/models.py #: lms/templates/support/feature_based_enrollments.html diff --git a/conf/locale/rtl/LC_MESSAGES/djangojs.mo b/conf/locale/rtl/LC_MESSAGES/djangojs.mo index 5492ae5b46..d85f0d6e36 100644 Binary files a/conf/locale/rtl/LC_MESSAGES/djangojs.mo and b/conf/locale/rtl/LC_MESSAGES/djangojs.mo differ diff --git a/conf/locale/rtl/LC_MESSAGES/djangojs.po b/conf/locale/rtl/LC_MESSAGES/djangojs.po index 008760a54a..76d9de1c11 100644 --- a/conf/locale/rtl/LC_MESSAGES/djangojs.po +++ b/conf/locale/rtl/LC_MESSAGES/djangojs.po @@ -32,8 +32,8 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-09-20 12:47+0000\n" -"PO-Revision-Date: 2023-09-20 12:47:19.757119\n" +"POT-Creation-Date: 2023-09-24 20:36+0000\n" +"PO-Revision-Date: 2023-09-24 20:36:20.294880\n" "Last-Translator: \n" "Language-Team: openedx-translation \n" "Language: rtl\n" diff --git a/conf/locale/sk/LC_MESSAGES/django.po b/conf/locale/sk/LC_MESSAGES/django.po index d444869067..b161a52878 100644 --- a/conf/locale/sk/LC_MESSAGES/django.po +++ b/conf/locale/sk/LC_MESSAGES/django.po @@ -55,7 +55,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Slovak (https://app.transifex.com/open-edx/teams/6205/sk/)\n" diff --git a/conf/locale/sw_KE/LC_MESSAGES/django.po b/conf/locale/sw_KE/LC_MESSAGES/django.po index 86a8f9fb03..e3ca02f5c6 100644 --- a/conf/locale/sw_KE/LC_MESSAGES/django.po +++ b/conf/locale/sw_KE/LC_MESSAGES/django.po @@ -85,7 +85,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Swahili (Kenya) (https://app.transifex.com/open-edx/teams/6205/sw_KE/)\n" diff --git a/conf/locale/th/LC_MESSAGES/django.po b/conf/locale/th/LC_MESSAGES/django.po index 6f2a74ede1..b33b18ec22 100644 --- a/conf/locale/th/LC_MESSAGES/django.po +++ b/conf/locale/th/LC_MESSAGES/django.po @@ -116,7 +116,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Thai (https://app.transifex.com/open-edx/teams/6205/th/)\n" diff --git a/conf/locale/uk/LC_MESSAGES/django.po b/conf/locale/uk/LC_MESSAGES/django.po index 7e07fc1047..2c79148d22 100644 --- a/conf/locale/uk/LC_MESSAGES/django.po +++ b/conf/locale/uk/LC_MESSAGES/django.po @@ -125,7 +125,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Danylo Shcherbak , 2020\n" "Language-Team: Ukrainian (https://app.transifex.com/open-edx/teams/6205/uk/)\n" diff --git a/conf/locale/vi/LC_MESSAGES/django.po b/conf/locale/vi/LC_MESSAGES/django.po index c61d56c393..891d04238c 100644 --- a/conf/locale/vi/LC_MESSAGES/django.po +++ b/conf/locale/vi/LC_MESSAGES/django.po @@ -198,7 +198,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Le Minh Tri , 2020\n" "Language-Team: Vietnamese (https://app.transifex.com/open-edx/teams/6205/vi/)\n" diff --git a/conf/locale/zh_CN/LC_MESSAGES/django.po b/conf/locale/zh_CN/LC_MESSAGES/django.po index b128bb14b0..b13d26e137 100644 --- a/conf/locale/zh_CN/LC_MESSAGES/django.po +++ b/conf/locale/zh_CN/LC_MESSAGES/django.po @@ -403,7 +403,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: ifLab , 2019\n" "Language-Team: Chinese (China) (https://app.transifex.com/open-edx/teams/6205/zh_CN/)\n" diff --git a/conf/locale/zh_HANS/LC_MESSAGES/django.po b/conf/locale/zh_HANS/LC_MESSAGES/django.po index b128bb14b0..b13d26e137 100644 --- a/conf/locale/zh_HANS/LC_MESSAGES/django.po +++ b/conf/locale/zh_HANS/LC_MESSAGES/django.po @@ -403,7 +403,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: ifLab , 2019\n" "Language-Team: Chinese (China) (https://app.transifex.com/open-edx/teams/6205/zh_CN/)\n" diff --git a/conf/locale/zh_TW/LC_MESSAGES/django.po b/conf/locale/zh_TW/LC_MESSAGES/django.po index ac047e66ce..d2bee32b49 100644 --- a/conf/locale/zh_TW/LC_MESSAGES/django.po +++ b/conf/locale/zh_TW/LC_MESSAGES/django.po @@ -177,7 +177,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1a\n" "Report-Msgid-Bugs-To: openedx-translation@googlegroups.com\n" -"POT-Creation-Date: 2023-08-27 20:43+0000\n" +"POT-Creation-Date: 2023-09-17 20:43+0000\n" "PO-Revision-Date: 2019-01-20 20:43+0000\n" "Last-Translator: Waheed Ahmed , 2019\n" "Language-Team: Chinese (Taiwan) (https://app.transifex.com/open-edx/teams/6205/zh_TW/)\n" diff --git a/openedx/core/djangoapps/notifications/admin.py b/openedx/core/djangoapps/notifications/admin.py index 9fd69af219..52a758b97b 100644 --- a/openedx/core/djangoapps/notifications/admin.py +++ b/openedx/core/djangoapps/notifications/admin.py @@ -3,17 +3,61 @@ Django Admin for Notifications """ from django.contrib import admin +from django.utils.translation import gettext_lazy as _ +from .base_notification import COURSE_NOTIFICATION_APPS, COURSE_NOTIFICATION_TYPES from .models import CourseNotificationPreference, Notification +class NotificationAppNameListFilter(admin.SimpleListFilter): + """ + Shows list filter in django admin of notification apps + """ + title = _("Notification App") + parameter_name = "app_name" + + def lookups(self, request, model_admin): + lookup_list = [ + (app_name, app_name) + for app_name in COURSE_NOTIFICATION_APPS.keys() + ] + return lookup_list + + def queryset(self, request, queryset): + app_name = self.value() + if app_name not in COURSE_NOTIFICATION_APPS.keys(): + return queryset + return queryset.filter(app_name=app_name) + + +class NotificationTypeListFilter(admin.SimpleListFilter): + """ + Shows list filter in django admin of notification types + """ + title = _("Notification Type") + parameter_name = "notification_type" + + def lookups(self, request, model_admin): + lookup_list = [ + (notification_type, notification_type) + for notification_type in COURSE_NOTIFICATION_TYPES.keys() + ] + return lookup_list + + def queryset(self, request, queryset): + notification_type = self.value() + if notification_type not in COURSE_NOTIFICATION_TYPES.keys(): + return queryset + return queryset.filter(notification_type=notification_type) + + class NotificationAdmin(admin.ModelAdmin): """ Admin for Notifications """ raw_id_fields = ('user',) - search_fields = ('course_id', 'user__username') - list_filter = ('app_name',) + search_fields = ('course_id', 'app_name', 'notification_type', 'user__username') + list_filter = (NotificationAppNameListFilter, NotificationTypeListFilter) class CourseNotificationPreferenceAdmin(admin.ModelAdmin): diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 58a103c543..50c78c4851 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -20,9 +20,8 @@ celery>=5.2.2,<6.0.0 # required for celery>=5.2.0;<5.3.0 click>=8.0,<9.0 -# django-storages version upgrade -django-storages==1.13.2 - +# each version upgrade need release notes review. +django-storages==1.14 # The team that owns this package will manually bump this package rather than having it pulled in automatically. # This is to allow them to better control its deployment and to do it in a process that works better @@ -33,7 +32,7 @@ edx-enterprise==4.3.1 # mentioned on this issue https://github.com/openedx/edx-platform/issues/32884 # 2. Versions from 1.5.0 to 2.0.0 have some migrations related changes. # so we're upgrading minor versions one by one. -django-oauth-toolkit==1.5.0 +django-oauth-toolkit==1.6.2 # constrained in opaque_keys. migration guide here: https://pymongo.readthedocs.io/en/4.0/migrate-to-pymongo4.html @@ -78,8 +77,7 @@ pylint<2.16.0 # greater version failing quality test. Fix them in seperate ticke # Deprecated version of the AWS SDK; # we should stop using this boto==2.39.0 -boto3==1.7.0 # Amazon Web Services SDK for Python -botocore==1.10.84 # via boto3, s3transfer + # adding these constraints to minimize boto3 and botocore changeset social-auth-core==4.3.0 @@ -134,3 +132,4 @@ openedx-learning==0.1.6 # existing custom parameter configurations unusable. # https://github.com/openedx/xblock-lti-consumer/issues/410 has been opened to track a fix lti-consumer-xblock==9.6.1 + diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index f0a5c00b1e..10891a48df 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -77,16 +77,14 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in -boto3==1.7.0 +boto3==1.28.53 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in # django-ses # fs-s3fs # ora2 -botocore==1.10.84 +botocore==1.31.53 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in # boto3 # s3transfer @@ -259,7 +257,7 @@ django-celery-results==2.5.1 # via -r requirements/edx/kernel.in django-classy-tags==4.1.0 # via django-sekizai -django-config-models==2.5.0 +django-config-models==2.5.1 # via # -r requirements/edx/kernel.in # edx-enterprise @@ -325,7 +323,7 @@ django-multi-email-field==0.7.0 # via edx-enterprise django-mysql==4.11.0 # via -r requirements/edx/kernel.in -django-oauth-toolkit==1.5.0 +django-oauth-toolkit==1.6.2 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in @@ -357,7 +355,7 @@ django-statici18n==2.4.0 # -r requirements/edx/kernel.in # lti-consumer-xblock # xblock-drag-and-drop-v2 -django-storages==1.13.2 +django-storages==1.14 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in @@ -402,10 +400,6 @@ djangorestframework==3.14.0 # super-csv djangorestframework-xml==2.0.0 # via edx-enterprise -docutils==0.19 - # via - # -c requirements/edx/../constraints.txt - # botocore done-xblock==2.1.0 # via -r requirements/edx/bundled.in drf-jwt==1.19.2 @@ -490,7 +484,7 @@ edx-enterprise==4.3.1 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/kernel.in -edx-event-bus-kafka==5.4.0 +edx-event-bus-kafka==5.5.0 # via -r requirements/edx/kernel.in edx-event-bus-redis==0.3.1 # via -r requirements/edx/kernel.in @@ -500,7 +494,7 @@ edx-milestones==0.5.0 # via -r requirements/edx/kernel.in edx-name-affirmation==2.3.6 # via -r requirements/edx/kernel.in -edx-opaque-keys[django]==2.5.0 +edx-opaque-keys[django]==2.5.1 # via # -r requirements/edx/kernel.in # -r requirements/edx/paver.txt @@ -636,7 +630,7 @@ jinja2==3.1.2 # via # code-annotations # coreschema -jmespath==0.10.0 +jmespath==1.0.1 # via # boto3 # botocore @@ -778,7 +772,7 @@ openedx-django-pyfs==3.4.0 # xblock openedx-django-require==2.1.0 # via -r requirements/edx/kernel.in -openedx-django-wiki==2.0.1 +openedx-django-wiki==2.0.3 # via -r requirements/edx/kernel.in openedx-events==8.5.0 # via @@ -1034,7 +1028,7 @@ rules==3.3 # edx-enterprise # edx-proctoring # openedx-learning -s3transfer==0.1.13 +s3transfer==0.6.2 # via boto3 sailthru-client==2.2.3 # via edx-ace @@ -1062,7 +1056,6 @@ six==1.16.0 # chem # codejail-includes # crowdsourcehinter-xblock - # django-oauth-toolkit # edx-ace # edx-auth-backends # edx-ccx-keys @@ -1170,6 +1163,7 @@ urllib3==1.26.16 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/paver.txt + # botocore # elasticsearch # py2neo # requests diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index d38dfac599..28e9b4f9f1 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -145,17 +145,15 @@ boto==2.39.0 # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -boto3==1.7.0 +boto3==1.28.53 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # django-ses # fs-s3fs # ora2 -botocore==1.10.84 +botocore==1.31.53 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # boto3 @@ -431,7 +429,7 @@ django-classy-tags==4.1.0 # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # django-sekizai -django-config-models==2.5.0 +django-config-models==2.5.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -524,7 +522,7 @@ django-mysql==4.11.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -django-oauth-toolkit==1.5.0 +django-oauth-toolkit==1.6.2 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt @@ -571,7 +569,7 @@ django-statici18n==2.4.0 # -r requirements/edx/testing.txt # lti-consumer-xblock # xblock-drag-and-drop-v2 -django-storages==1.13.2 +django-storages==1.14 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt @@ -640,8 +638,6 @@ docutils==0.19 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt - # -r requirements/edx/testing.txt - # botocore # pydata-sphinx-theme # sphinx # sphinx-mdinclude @@ -759,7 +755,7 @@ edx-enterprise==4.3.1 # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -edx-event-bus-kafka==5.4.0 +edx-event-bus-kafka==5.5.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -782,7 +778,7 @@ edx-name-affirmation==2.3.6 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -edx-opaque-keys[django]==2.5.0 +edx-opaque-keys[django]==2.5.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -950,7 +946,7 @@ gitdb==4.0.10 # via # -r requirements/edx/doc.txt # gitpython -gitpython==3.1.36 +gitpython==3.1.37 # via -r requirements/edx/doc.txt glob2==0.7 # via @@ -1064,7 +1060,7 @@ jinja2==3.1.2 # coreschema # diff-cover # sphinx -jmespath==0.10.0 +jmespath==1.0.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1305,7 +1301,7 @@ openedx-django-require==2.1.0 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt -openedx-django-wiki==2.0.1 +openedx-django-wiki==2.0.3 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1792,7 +1788,7 @@ rules==3.3 # edx-enterprise # edx-proctoring # openedx-learning -s3transfer==0.1.13 +s3transfer==0.6.2 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -1841,7 +1837,6 @@ six==1.16.0 # chem # codejail-includes # crowdsourcehinter-xblock - # django-oauth-toolkit # edx-ace # edx-auth-backends # edx-ccx-keys @@ -2118,6 +2113,7 @@ urllib3==1.26.16 # -c requirements/edx/../constraints.txt # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt + # botocore # elasticsearch # pact-python # py2neo diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index b27cca0f46..c168388afa 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -103,16 +103,14 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt -boto3==1.7.0 +boto3==1.28.53 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt # django-ses # fs-s3fs # ora2 -botocore==1.10.84 +botocore==1.31.53 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt # boto3 # s3transfer @@ -312,7 +310,7 @@ django-classy-tags==4.1.0 # via # -r requirements/edx/base.txt # django-sekizai -django-config-models==2.5.0 +django-config-models==2.5.1 # via # -r requirements/edx/base.txt # edx-enterprise @@ -386,7 +384,7 @@ django-multi-email-field==0.7.0 # edx-enterprise django-mysql==4.11.0 # via -r requirements/edx/base.txt -django-oauth-toolkit==1.5.0 +django-oauth-toolkit==1.6.2 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt @@ -420,7 +418,7 @@ django-statici18n==2.4.0 # -r requirements/edx/base.txt # lti-consumer-xblock # xblock-drag-and-drop-v2 -django-storages==1.13.2 +django-storages==1.14 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt @@ -470,8 +468,6 @@ djangorestframework-xml==2.0.0 docutils==0.19 # via # -c requirements/edx/../constraints.txt - # -r requirements/edx/base.txt - # botocore # pydata-sphinx-theme # sphinx # sphinx-mdinclude @@ -564,7 +560,7 @@ edx-enterprise==4.3.1 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt -edx-event-bus-kafka==5.4.0 +edx-event-bus-kafka==5.5.0 # via -r requirements/edx/base.txt edx-event-bus-redis==0.3.1 # via -r requirements/edx/base.txt @@ -576,7 +572,7 @@ edx-milestones==0.5.0 # via -r requirements/edx/base.txt edx-name-affirmation==2.3.6 # via -r requirements/edx/base.txt -edx-opaque-keys[django]==2.5.0 +edx-opaque-keys[django]==2.5.1 # via # -r requirements/edx/base.txt # edx-bulk-grades @@ -686,7 +682,7 @@ geoip2==4.7.0 # via -r requirements/edx/base.txt gitdb==4.0.10 # via gitpython -gitpython==3.1.36 +gitpython==3.1.37 # via -r requirements/edx/doc.in glob2==0.7 # via -r requirements/edx/base.txt @@ -744,7 +740,7 @@ jinja2==3.1.2 # code-annotations # coreschema # sphinx -jmespath==0.10.0 +jmespath==1.0.1 # via # -r requirements/edx/base.txt # boto3 @@ -916,7 +912,7 @@ openedx-django-pyfs==3.4.0 # xblock openedx-django-require==2.1.0 # via -r requirements/edx/base.txt -openedx-django-wiki==2.0.1 +openedx-django-wiki==2.0.3 # via -r requirements/edx/base.txt openedx-events==8.5.0 # via @@ -1222,7 +1218,7 @@ rules==3.3 # edx-enterprise # edx-proctoring # openedx-learning -s3transfer==0.1.13 +s3transfer==0.6.2 # via # -r requirements/edx/base.txt # boto3 @@ -1256,7 +1252,6 @@ six==1.16.0 # chem # codejail-includes # crowdsourcehinter-xblock - # django-oauth-toolkit # edx-ace # edx-auth-backends # edx-ccx-keys @@ -1425,6 +1420,7 @@ urllib3==1.26.16 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt + # botocore # elasticsearch # py2neo # requests diff --git a/requirements/edx/paver.txt b/requirements/edx/paver.txt index 962fdec088..46af4d76cc 100644 --- a/requirements/edx/paver.txt +++ b/requirements/edx/paver.txt @@ -10,7 +10,7 @@ charset-normalizer==2.0.12 # via # -c requirements/edx/../constraints.txt # requests -edx-opaque-keys==2.5.0 +edx-opaque-keys==2.5.1 # via -r requirements/edx/paver.in idna==3.4 # via requests diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 18134e0ea5..6dc45b85a7 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -110,16 +110,14 @@ boto==2.39.0 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt -boto3==1.7.0 +boto3==1.28.53 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt # django-ses # fs-s3fs # ora2 -botocore==1.10.84 +botocore==1.31.53 # via - # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt # boto3 # s3transfer @@ -345,7 +343,7 @@ django-classy-tags==4.1.0 # via # -r requirements/edx/base.txt # django-sekizai -django-config-models==2.5.0 +django-config-models==2.5.1 # via # -r requirements/edx/base.txt # edx-enterprise @@ -419,7 +417,7 @@ django-multi-email-field==0.7.0 # edx-enterprise django-mysql==4.11.0 # via -r requirements/edx/base.txt -django-oauth-toolkit==1.5.0 +django-oauth-toolkit==1.6.2 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt @@ -453,7 +451,7 @@ django-statici18n==2.4.0 # -r requirements/edx/base.txt # lti-consumer-xblock # xblock-drag-and-drop-v2 -django-storages==1.13.2 +django-storages==1.14 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt @@ -500,11 +498,6 @@ djangorestframework-xml==2.0.0 # via # -r requirements/edx/base.txt # edx-enterprise -docutils==0.19 - # via - # -c requirements/edx/../constraints.txt - # -r requirements/edx/base.txt - # botocore done-xblock==2.1.0 # via -r requirements/edx/base.txt drf-jwt==1.19.2 @@ -594,7 +587,7 @@ edx-enterprise==4.3.1 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt -edx-event-bus-kafka==5.4.0 +edx-event-bus-kafka==5.5.0 # via -r requirements/edx/base.txt edx-event-bus-redis==0.3.1 # via -r requirements/edx/base.txt @@ -609,7 +602,7 @@ edx-milestones==0.5.0 # via -r requirements/edx/base.txt edx-name-affirmation==2.3.6 # via -r requirements/edx/base.txt -edx-opaque-keys[django]==2.5.0 +edx-opaque-keys[django]==2.5.1 # via # -r requirements/edx/base.txt # edx-bulk-grades @@ -810,7 +803,7 @@ jinja2==3.1.2 # code-annotations # coreschema # diff-cover -jmespath==0.10.0 +jmespath==1.0.1 # via # -r requirements/edx/base.txt # boto3 @@ -986,7 +979,7 @@ openedx-django-pyfs==3.4.0 # xblock openedx-django-require==2.1.0 # via -r requirements/edx/base.txt -openedx-django-wiki==2.0.1 +openedx-django-wiki==2.0.3 # via -r requirements/edx/base.txt openedx-events==8.5.0 # via @@ -1359,7 +1352,7 @@ rules==3.3 # edx-enterprise # edx-proctoring # openedx-learning -s3transfer==0.1.13 +s3transfer==0.6.2 # via # -r requirements/edx/base.txt # boto3 @@ -1399,7 +1392,6 @@ six==1.16.0 # chem # codejail-includes # crowdsourcehinter-xblock - # django-oauth-toolkit # edx-ace # edx-auth-backends # edx-ccx-keys @@ -1565,6 +1557,7 @@ urllib3==1.26.16 # via # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt + # botocore # elasticsearch # pact-python # py2neo