diff --git a/cms/lib/spectacular.py b/cms/lib/spectacular.py index 57a11513cb60..90bce5668fec 100644 --- a/cms/lib/spectacular.py +++ b/cms/lib/spectacular.py @@ -12,9 +12,12 @@ def cms_api_filter(endpoints): CMS_PATH_PATTERN = re.compile(r"^/api/contentstore/v\d+/") for path, path_regex, method, callback in endpoints: - if CMS_PATH_PATTERN.match(path) or ( - path.startswith("/api/courses/") - and "bulk_enable_disable_discussions" in path + if ( + CMS_PATH_PATTERN.match(path) + or ( + path.startswith("/api/courses/") + and "bulk_enable_disable_discussions" in path + ) ): filtered.append((path, path_regex, method, callback)) diff --git a/lms/envs/common.py b/lms/envs/common.py index 828c7874152b..2d763827203c 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2040,6 +2040,7 @@ # API Documentation 'drf_yasg', + 'drf_spectacular', # edx-drf-extensions 'csrf.apps.CsrfAppConfig', # Enables frontend apps to retrieve CSRF tokens. @@ -2125,6 +2126,18 @@ 'DEEP_LINKING': True, } +###################### drf-spectacular (LMS enrollment schema) ###################### +SPECTACULAR_SETTINGS = { + 'TITLE': 'LMS Enrollment API', + 'VERSION': '0.1.0', + 'SERVE_INCLUDE_SCHEMA': False, + 'PREPROCESSING_HOOKS': ['lms.lib.spectacular.lms_api_filter'], + 'SCHEMA_PATH_PREFIX': '/api/enrollment', + 'SCHEMA_PATH_PREFIX_TRIM': '/api/enrollment', + # SERVERS is environment-specific (LMS_ROOT_URL differs per env) and is + # set in devstack.py / production.py. +} + ######################### MARKETING SITE ############################### MKTG_URL_LINK_MAP.update({ # noqa: F405 diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py index 1043016a6b2b..68fbd5cc1017 100644 --- a/lms/envs/devstack.py +++ b/lms/envs/devstack.py @@ -582,6 +582,11 @@ def should_show_debug_toolbar(request): # pylint: disable=missing-function-docs 'COMPLETE', ] +###################### drf-spectacular (LMS enrollment schema) ###################### +SPECTACULAR_SETTINGS['SERVERS'] = [ # noqa: F405 + {'url': LMS_ROOT_URL, 'description': 'Local'}, # noqa: F405 +] + ################# New settings must go ABOVE this line ################# ######################################################################## # See if the developer has any local overrides. diff --git a/lms/envs/production.py b/lms/envs/production.py index b954841d59bc..b38a26822f98 100644 --- a/lms/envs/production.py +++ b/lms/envs/production.py @@ -397,6 +397,11 @@ def get_env_setting(setting): MIDDLEWARE.extend(_YAML_TOKENS.get('EXTRA_MIDDLEWARE_CLASSES', [])) # noqa: F405 +###################### drf-spectacular (LMS enrollment schema) ###################### +SPECTACULAR_SETTINGS['SERVERS'] = [ # noqa: F405 + {'url': LMS_ROOT_URL, 'description': 'Local'}, # noqa: F405 +] + ####################################################################################################################### #### DERIVE ANY DERIVED SETTINGS #### diff --git a/lms/lib/spectacular.py b/lms/lib/spectacular.py new file mode 100644 index 000000000000..433b05f6db11 --- /dev/null +++ b/lms/lib/spectacular.py @@ -0,0 +1,17 @@ +"""Helper functions for drf-spectacular (LMS schema).""" + +import re + + +def lms_api_filter(endpoints): + """ + Pre-processing hook: keep only enrollment v2 endpoints tagged for the SDK. + """ + filtered = [] + ENROLLMENT_PATH_PATTERN = re.compile(r"^/api/enrollment/v\d+/") + + for path, path_regex, method, callback in endpoints: + if ENROLLMENT_PATH_PATTERN.match(path): + filtered.append((path, path_regex, method, callback)) + + return filtered diff --git a/lms/urls.py b/lms/urls.py index 280c739c9bce..032dbb8b1c60 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -10,6 +10,7 @@ from django.urls import include, path, re_path from django.utils.translation import gettext_lazy as _ from django.views.generic.base import RedirectView +from drf_spectacular.views import SpectacularAPIView from edx_api_doc_tools import make_docs_urls from edx_django_utils.plugins import get_plugin_url_patterns from submissions import urls as submissions_urls @@ -1068,3 +1069,8 @@ urlpatterns += [ path('xqueue/', include((submissions_urls, 'submissions'), namespace='submissions')), ] + +# LMS API schema for openedx-platform-sdk generation. +urlpatterns += [ + path('lms-api/schema/', SpectacularAPIView.as_view(), name='lms-schema'), +] diff --git a/openedx/envs/common.py b/openedx/envs/common.py index 31b0015d34d9..673b915f1d0a 100644 --- a/openedx/envs/common.py +++ b/openedx/envs/common.py @@ -836,6 +836,7 @@ def add_optional_apps(optional_apps, installed_apps): 'registration_validation': '30/minute', 'high_service_user': '2000/minute', }, + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', } # .. setting_name: REGISTRATION_VALIDATION_RATELIMIT