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..dd05f231 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,15 @@ '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', +} + +SPECTACULAR_SETTINGS = { + 'TITLE': 'Edx Notes API', + 'DESCRIPTION': 'Edx Notes API docs', + 'VERSION': '1.0.0', + 'SERVE_INCLUDE_SCHEMA': False, + 'SCHEMA_PATH_PREFIX': '/api/' } # CORS is configured to allow all origins because requests to 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 51e5e8e1..77793f6a 100644 --- a/notesserver/urls.py +++ b/notesserver/urls.py @@ -1,25 +1,15 @@ 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, SpectacularRedocView, 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'), + path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'), ] diff --git a/requirements/base.in b/requirements/base.in index 4719fdf6..d0978e72 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 @@ -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 1b1bed88..05398f1d 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,17 +62,17 @@ 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 -edx-django-utils==5.15.0 +edx-django-utils==5.16.0 # via # -r requirements/base.in # edx-drf-extensions @@ -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==10.0.0 @@ -104,7 +112,6 @@ newrelic==10.0.0 packaging==24.1 # via # django-nine - # drf-yasg # gunicorn path-py==9.1 # via @@ -121,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 @@ -131,16 +138,24 @@ 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-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 +174,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/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 82c5724e..ea169672 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,11 +108,11 @@ 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 -edx-django-utils==5.15.0 +edx-django-utils==5.16.0 # via # -r requirements/base.txt # edx-drf-extensions @@ -132,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 @@ -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 @@ -214,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 @@ -240,20 +252,28 @@ 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 # 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 @@ -288,10 +308,11 @@ typing-extensions==4.12.2 # via # -r requirements/base.txt # edx-opaque-keys + # faker uritemplate==4.1.1 # via # -r requirements/base.txt - # drf-yasg + # drf-spectacular urllib3==1.26.20 # via # -r requirements/base.txt