From 35a9435107634c1f2666831a33278cfbdd0b5eae Mon Sep 17 00:00:00 2001 From: Irtaza Akram Date: Fri, 13 Sep 2024 16:05:58 +0500 Subject: [PATCH 1/4] fix: move to drf-spectacular --- notesapi/v1/models.py | 2 +- notesapi/v1/views.py | 2 +- notesserver/settings/common.py | 5 ++-- notesserver/urls.py | 17 +++----------- requirements/base.in | 2 +- requirements/base.txt | 31 +++++++++++++++++-------- requirements/test.txt | 42 ++++++++++++++++++++++++---------- 7 files changed, 61 insertions(+), 40 deletions(-) diff --git a/notesapi/v1/models.py b/notesapi/v1/models.py index 571aeba0..72f8548a 100644 --- a/notesapi/v1/models.py +++ b/notesapi/v1/models.py @@ -11,7 +11,7 @@ class Note(models.Model): .. pii:: Stores 'text' and 'tags' about a particular course quote. .. pii_types:: other .. pii_retirement:: local_api, consumer_api - """ + """ user_id = models.CharField(max_length=255, db_index=True, help_text="Anonymized user id, not course specific") course_id = models.CharField(max_length=255, db_index=True) usage_id = models.CharField(max_length=255, help_text="ID of XBlock where the text comes from") diff --git a/notesapi/v1/views.py b/notesapi/v1/views.py index 4877990a..872c5c17 100644 --- a/notesapi/v1/views.py +++ b/notesapi/v1/views.py @@ -122,7 +122,7 @@ class AnnotationSearchView(ListAPIView): * updated: DateTime. When was the last time annotation was updated. """ - action = None + action = '' params = {} query_params = {} search_with_usage_id = False diff --git a/notesserver/settings/common.py b/notesserver/settings/common.py index 857804a4..c29e55db 100644 --- a/notesserver/settings/common.py +++ b/notesserver/settings/common.py @@ -10,7 +10,7 @@ # This value needs to be overriden in production. SECRET_KEY = 'CHANGEME' -ALLOWED_HOSTS = ['localhost'] +ALLOWED_HOSTS = ['*'] # ID and Secret used for authenticating JWT Auth Tokens # should match those configured for `edx-notes` Client in EdX's /admin/oauth2/client/ @@ -57,12 +57,12 @@ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.staticfiles', - 'drf_yasg', 'rest_framework', 'corsheaders', 'notesapi.v1', # additional release utilities to ease automation 'release_util', + 'drf_spectacular', ] if not ES_DISABLED: INSTALLED_APPS.extend(ES_APPS) @@ -84,6 +84,7 @@ 'DEFAULT_PERMISSION_CLASSES': ['notesapi.v1.permissions.HasAccessToken'], 'DEFAULT_PAGINATION_CLASS': 'notesapi.v1.paginators.NotesPaginator', 'DEFAULT_RENDERER_CLASSES': ('rest_framework.renderers.JSONRenderer',), + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', } # CORS is configured to allow all origins because requests to the diff --git a/notesserver/urls.py b/notesserver/urls.py index 51e5e8e1..b0608095 100644 --- a/notesserver/urls.py +++ b/notesserver/urls.py @@ -1,25 +1,14 @@ from django.urls import include, path, re_path -from drf_yasg.views import get_schema_view -from drf_yasg import openapi -from rest_framework import permissions +from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView import notesserver.views -schema_view = get_schema_view( - openapi.Info( - title="Edx Notes API", - default_version='v1', - description="Edx Notes API docs", - ), - public=False, - permission_classes=[permissions.AllowAny], -) - urlpatterns = [ path('heartbeat/', notesserver.views.heartbeat, name='heartbeat'), path('selftest/', notesserver.views.selftest, name='selftest'), re_path(r'^robots.txt$', notesserver.views.robots, name='robots'), path('', notesserver.views.root, name='root'), path('api/', include('notesapi.urls', namespace='api')), - path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), + path('api/schema/', SpectacularAPIView.as_view(), name='schema'), + path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), ] diff --git a/requirements/base.in b/requirements/base.in index 4719fdf6..2fa8cd3f 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -4,7 +4,7 @@ Django requests djangorestframework -drf-yasg +drf-spectacular elasticsearch elasticsearch-dsl django-elasticsearch-dsl diff --git a/requirements/base.txt b/requirements/base.txt index 42e74787..784d0310 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -6,6 +6,10 @@ # asgiref==3.8.1 # via django +attrs==24.2.0 + # via + # jsonschema + # referencing certifi==2024.8.30 # via # elasticsearch @@ -30,7 +34,7 @@ django==4.2.16 # django-waffle # djangorestframework # drf-jwt - # drf-yasg + # drf-spectacular # edx-django-release-util # edx-django-utils # edx-drf-extensions @@ -58,13 +62,13 @@ djangorestframework==3.15.2 # -r requirements/base.in # django-elasticsearch-dsl-drf # drf-jwt - # drf-yasg + # drf-spectacular # edx-drf-extensions dnspython==2.6.1 # via pymongo drf-jwt==1.19.2 # via edx-drf-extensions -drf-yasg==1.21.7 +drf-spectacular==0.27.2 # via -r requirements/base.in edx-django-release-util==1.4.0 # via -r requirements/base.in @@ -94,7 +98,11 @@ gunicorn==23.0.0 idna==2.10 # via requests inflection==0.5.1 - # via drf-yasg + # via drf-spectacular +jsonschema==4.23.0 + # via drf-spectacular +jsonschema-specifications==2023.12.1 + # via jsonschema mysqlclient==2.2.4 # via -r requirements/base.in newrelic==9.13.0 @@ -104,7 +112,6 @@ newrelic==9.13.0 packaging==24.1 # via # django-nine - # drf-yasg # gunicorn path-py==9.1 # via @@ -130,17 +137,23 @@ python-dateutil==2.4.0 # -c requirements/constraints.txt # -r requirements/base.in # elasticsearch-dsl -pytz==2024.1 - # via drf-yasg pyyaml==6.0.2 # via - # drf-yasg + # drf-spectacular # edx-django-release-util +referencing==0.35.1 + # via + # jsonschema + # jsonschema-specifications requests==2.25.0 # via # -c requirements/constraints.txt # -r requirements/base.in # edx-drf-extensions +rpds-py==0.20.0 + # via + # jsonschema + # referencing semantic-version==2.10.0 # via edx-drf-extensions six==1.16.0 @@ -159,7 +172,7 @@ stevedore==5.3.0 typing-extensions==4.12.2 # via edx-opaque-keys uritemplate==4.1.1 - # via drf-yasg + # via drf-spectacular urllib3==1.26.20 # via # elasticsearch diff --git a/requirements/test.txt b/requirements/test.txt index cbb8e490..2c735eba 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -13,6 +13,11 @@ astroid==1.6.6 # -c requirements/constraints.txt # -r requirements/test.in # pylint +attrs==24.2.0 + # via + # -r requirements/base.txt + # jsonschema + # referencing certifi==2024.8.30 # via # -r requirements/base.txt @@ -60,7 +65,7 @@ distlib==0.3.8 # django-waffle # djangorestframework # drf-jwt - # drf-yasg + # drf-spectacular # edx-django-release-util # edx-django-utils # edx-drf-extensions @@ -93,7 +98,7 @@ djangorestframework==3.15.2 # -r requirements/base.txt # django-elasticsearch-dsl-drf # drf-jwt - # drf-yasg + # drf-spectacular # edx-drf-extensions dnspython==2.6.1 # via @@ -103,7 +108,7 @@ drf-jwt==1.19.2 # via # -r requirements/base.txt # edx-drf-extensions -drf-yasg==1.21.7 +drf-spectacular==0.27.2 # via -r requirements/base.txt edx-django-release-util==1.4.0 # via -r requirements/base.txt @@ -147,13 +152,21 @@ idna==2.10 inflection==0.5.1 # via # -r requirements/base.txt - # drf-yasg + # drf-spectacular iniconfig==2.0.0 # via pytest jinja2==3.1.4 # via # code-annotations # diff-cover +jsonschema==4.23.0 + # via + # -r requirements/base.txt + # drf-spectacular +jsonschema-specifications==2023.12.1 + # via + # -r requirements/base.txt + # jsonschema lazy-object-proxy==1.10.0 # via astroid markupsafe==2.1.5 @@ -172,7 +185,6 @@ packaging==24.1 # via # -r requirements/base.txt # django-nine - # drf-yasg # gunicorn # pytest # tox @@ -222,7 +234,7 @@ pynacl==1.5.0 # via # -r requirements/base.txt # edx-django-utils -pytest==8.3.2 +pytest==8.3.3 # via # -r requirements/test.in # pytest-cov @@ -239,21 +251,27 @@ python-dateutil==2.4.0 # faker python-slugify==8.0.4 # via code-annotations -pytz==2024.1 - # via - # -r requirements/base.txt - # drf-yasg pyyaml==6.0.2 # via # -r requirements/base.txt # code-annotations - # drf-yasg + # drf-spectacular # edx-django-release-util +referencing==0.35.1 + # via + # -r requirements/base.txt + # jsonschema + # jsonschema-specifications requests==2.25.0 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-drf-extensions +rpds-py==0.20.0 + # via + # -r requirements/base.txt + # jsonschema + # referencing semantic-version==2.10.0 # via # -r requirements/base.txt @@ -291,7 +309,7 @@ typing-extensions==4.12.2 uritemplate==4.1.1 # via # -r requirements/base.txt - # drf-yasg + # drf-spectacular urllib3==1.26.20 # via # -r requirements/base.txt From c06684cb755140e09a8b796603a87afeec502f80 Mon Sep 17 00:00:00 2001 From: Irtaza Akram Date: Fri, 13 Sep 2024 19:15:05 +0500 Subject: [PATCH 2/4] fix: pytz dependency --- requirements/base.in | 1 + requirements/base.txt | 2 ++ requirements/test.txt | 2 ++ 3 files changed, 5 insertions(+) diff --git a/requirements/base.in b/requirements/base.in index 2fa8cd3f..d0978e72 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -19,3 +19,4 @@ newrelic edx-django-release-util edx-django-utils edx-drf-extensions +pytz diff --git a/requirements/base.txt b/requirements/base.txt index 784d0310..547222d0 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -137,6 +137,8 @@ python-dateutil==2.4.0 # -c requirements/constraints.txt # -r requirements/base.in # elasticsearch-dsl +pytz==2024.2 + # via -r requirements/base.in pyyaml==6.0.2 # via # drf-spectacular diff --git a/requirements/test.txt b/requirements/test.txt index 2c735eba..7601d30c 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -251,6 +251,8 @@ python-dateutil==2.4.0 # faker python-slugify==8.0.4 # via code-annotations +pytz==2024.2 + # via -r requirements/base.txt pyyaml==6.0.2 # via # -r requirements/base.txt From eec767c75a49b09b3628744290c1c8dc9a7b6bc2 Mon Sep 17 00:00:00 2001 From: Irtaza Akram Date: Wed, 2 Oct 2024 11:10:59 +0500 Subject: [PATCH 3/4] fix: add redoc & spectacular settings --- notesserver/settings/common.py | 8 ++++++++ notesserver/settings/logger.py | 1 + notesserver/settings/yaml_config.py | 2 +- notesserver/urls.py | 3 ++- requirements/base.txt | 6 +++--- requirements/ci.txt | 2 +- requirements/test.txt | 11 +++++------ 7 files changed, 21 insertions(+), 12 deletions(-) diff --git a/notesserver/settings/common.py b/notesserver/settings/common.py index c29e55db..74ea1806 100644 --- a/notesserver/settings/common.py +++ b/notesserver/settings/common.py @@ -87,6 +87,14 @@ 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', } +SPECTACULAR_SETTINGS = { + 'TITLE': 'edx-notes-api', + 'DESCRIPTION': 'API documentation for edx-notes-api', + 'VERSION': '1.0.0', + 'SERVE_INCLUDE_SCHEMA': False, + 'SCHEMA_PATH_PREFIX': '/api/' +} + # CORS is configured to allow all origins because requests to the # Notes API do not rely on ambient authority; instead, they are # authorized explicitly via an X-Annotator-Auth-Token header. (The diff --git a/notesserver/settings/logger.py b/notesserver/settings/logger.py index cff75bfa..be084b9e 100644 --- a/notesserver/settings/logger.py +++ b/notesserver/settings/logger.py @@ -6,6 +6,7 @@ import platform import sys from logging.handlers import SysLogHandler + from django.conf import settings diff --git a/notesserver/settings/yaml_config.py b/notesserver/settings/yaml_config.py index 35fb1dbc..38262cc2 100644 --- a/notesserver/settings/yaml_config.py +++ b/notesserver/settings/yaml_config.py @@ -2,9 +2,9 @@ import yaml from django.core.exceptions import ImproperlyConfigured +from path import path from notesserver.settings.logger import build_logging_config -from path import path from .common import * # pylint: disable=unused-wildcard-import, wildcard-import diff --git a/notesserver/urls.py b/notesserver/urls.py index b0608095..77793f6a 100644 --- a/notesserver/urls.py +++ b/notesserver/urls.py @@ -1,5 +1,5 @@ from django.urls import include, path, re_path -from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView +from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView import notesserver.views @@ -11,4 +11,5 @@ path('api/', include('notesapi.urls', namespace='api')), path('api/schema/', SpectacularAPIView.as_view(), name='schema'), path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), + path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'), ] diff --git a/requirements/base.txt b/requirements/base.txt index 396fa6ee..05398f1d 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -72,7 +72,7 @@ drf-spectacular==0.27.2 # via -r requirements/base.in edx-django-release-util==1.4.0 # via -r requirements/base.in -edx-django-utils==5.15.0 +edx-django-utils==5.16.0 # via # -r requirements/base.in # edx-drf-extensions @@ -128,7 +128,7 @@ pyjwt[crypto]==2.9.0 # -r requirements/base.in # drf-jwt # edx-drf-extensions -pymongo==4.9.1 +pymongo==4.10.1 # via edx-opaque-keys pynacl==1.5.0 # via edx-django-utils @@ -138,7 +138,7 @@ python-dateutil==2.4.0 # -r requirements/base.in # elasticsearch-dsl pytz==2024.2 - # via drf-yasg + # via -r requirements/base.in pyyaml==6.0.2 # via # drf-spectacular diff --git a/requirements/ci.txt b/requirements/ci.txt index b13ad897..8fa9d54c 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -28,7 +28,7 @@ pluggy==1.5.0 # via tox pyproject-api==1.8.0 # via tox -tox==4.20.0 +tox==4.21.0 # via -r requirements/ci.in virtualenv==20.26.6 # via tox diff --git a/requirements/test.txt b/requirements/test.txt index f274c8d7..ea169672 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -112,7 +112,7 @@ drf-spectacular==0.27.2 # via -r requirements/base.txt edx-django-release-util==1.4.0 # via -r requirements/base.txt -edx-django-utils==5.15.0 +edx-django-utils==5.16.0 # via # -r requirements/base.txt # edx-drf-extensions @@ -137,7 +137,7 @@ elasticsearch-dsl==7.4.1 # django-elasticsearch-dsl-drf factory-boy==3.3.1 # via -r requirements/test.in -faker==30.0.0 +faker==30.1.0 # via factory-boy filelock==3.16.1 # via @@ -226,7 +226,7 @@ pylint==1.5.0 # via # -c requirements/constraints.txt # -r requirements/test.in -pymongo==4.9.1 +pymongo==4.10.1 # via # -r requirements/base.txt # edx-opaque-keys @@ -252,9 +252,7 @@ python-dateutil==2.4.0 python-slugify==8.0.4 # via code-annotations pytz==2024.2 - # via - # -r requirements/base.txt - # drf-yasg + # via -r requirements/base.txt pyyaml==6.0.2 # via # -r requirements/base.txt @@ -310,6 +308,7 @@ typing-extensions==4.12.2 # via # -r requirements/base.txt # edx-opaque-keys + # faker uritemplate==4.1.1 # via # -r requirements/base.txt From 23b830600d901ce36287def075737b0287a330c0 Mon Sep 17 00:00:00 2001 From: Irtaza Akram Date: Wed, 2 Oct 2024 11:13:40 +0500 Subject: [PATCH 4/4] fix: title & description --- notesserver/settings/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notesserver/settings/common.py b/notesserver/settings/common.py index 74ea1806..dd05f231 100644 --- a/notesserver/settings/common.py +++ b/notesserver/settings/common.py @@ -88,8 +88,8 @@ } SPECTACULAR_SETTINGS = { - 'TITLE': 'edx-notes-api', - 'DESCRIPTION': 'API documentation for edx-notes-api', + 'TITLE': 'Edx Notes API', + 'DESCRIPTION': 'Edx Notes API docs', 'VERSION': '1.0.0', 'SERVE_INCLUDE_SCHEMA': False, 'SCHEMA_PATH_PREFIX': '/api/'