diff --git a/eox_tenant/api/v1/viewsets.py b/eox_tenant/api/v1/viewsets.py index 235d08b6..e82ac7b2 100644 --- a/eox_tenant/api/v1/viewsets.py +++ b/eox_tenant/api/v1/viewsets.py @@ -3,6 +3,7 @@ """ import logging +from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from rest_framework import viewsets from rest_framework.authentication import SessionAuthentication from rest_framework.parsers import JSONParser @@ -241,7 +242,7 @@ class MicrositeViewSet(AlternativeFieldLookupMixin, viewsets.ModelViewSet): Response: No content status code 204 """ - authentication_classes = (BearerAuthentication, SessionAuthentication) + authentication_classes = (BearerAuthentication, SessionAuthentication, JwtAuthentication) parser_classes = [JSONParser] permission_classes = [EoxTenantAPIPermission] serializer_class = MicrositeSerializer @@ -439,7 +440,7 @@ class TenantConfigViewSet(AlternativeFieldLookupMixin, viewsets.ModelViewSet): Response: No content status code 204 """ - authentication_classes = (BearerAuthentication, SessionAuthentication) + authentication_classes = (BearerAuthentication, SessionAuthentication, JwtAuthentication) parser_classes = [JSONParser] permission_classes = [EoxTenantAPIPermission] serializer_class = TenantConfigSerializer @@ -450,7 +451,7 @@ class TenantConfigViewSet(AlternativeFieldLookupMixin, viewsets.ModelViewSet): class RouteViewSet(viewsets.ModelViewSet): """RouteViewSet that allows the basic API actions.""" - authentication_classes = (BearerAuthentication, SessionAuthentication) + authentication_classes = (BearerAuthentication, SessionAuthentication, JwtAuthentication) parser_classes = [JSONParser] permission_classes = [EoxTenantAPIPermission] serializer_class = RouteSerializer diff --git a/eox_tenant/docs/resources/eox-tenant-test.postman_collection.json b/eox_tenant/docs/resources/eox-tenant-test.postman_collection.json new file mode 100644 index 00000000..357e1676 --- /dev/null +++ b/eox_tenant/docs/resources/eox-tenant-test.postman_collection.json @@ -0,0 +1,520 @@ +{ + "info": { + "_postman_id": "9f1933c5-e85b-438e-809f-151e8b160436", + "name": "eox-tenant API", + "description": "# Steps\n\n- You must create a new `access_token` using the `Authorization` endpoint. Make sure you have the correct credentials. To consume the `eox-tenant` API you should create a new application from `{domain}/admin/oauth2_provider/application/`\n- If you are using an environment within **Postman**, once you make the request the access token will be automatically added in the **Header** of all endpoints. The only thing you have to do is to use the variable access_token in the **Token** field of the **Current Token** section.\n \n- In case it doesn't work, copy the `access_token` from the response and paste it in the **Authorization** tab of this collection. In the **Current Token** section, add the access token manually, and modify the **Header Prefix** field depending on the type of token you are using.\n \n\n\"Current%20Token%20section%20in%20Authorization%20tab\"\n\n- Now, you can consume any endpoint without having to manually add the token on each of them.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "27731142" + }, + "item": [ + { + "name": "Microsites API", + "item": [ + { + "name": "Get MicroSites", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/microsites/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "microsites", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get MicroSite", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/microsites/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "microsites", + "1", + "" + ] + } + }, + "response": [] + }, + { + "name": "Create MicroSites", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"key\": \"key\",\n\t\"subdomain\": \"subdomain\",\n\t\"values\": {}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/microsites/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "microsites", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete MicroSite", + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/microsites/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "microsites", + "1", + "" + ] + } + }, + "response": [] + }, + { + "name": "Update MicroSite", + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"key\": \"key\",\n\t\"subdomain\": \"subdomain\",\n\t\"values\": {}\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/microsites/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "microsites", + "1", + "" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Configs API", + "item": [ + { + "name": "Get Configs", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/configs/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "configs", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get Config", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/configs/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "configs", + "1", + "" + ] + } + }, + "response": [] + }, + { + "name": "Create Config", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"lms_configs\": {},\n\t\"studio_configs\": {},\n\t\"theming_configs\": {},\n\t\"meta\": \"meta\",\n\t\"external_key\": \"external-key\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/configs/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "configs", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete Config", + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/configs/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "configs", + "1", + "" + ] + } + }, + "response": [] + }, + { + "name": "Update Config", + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"lms_configs\": {},\n\t\"studio_configs\": {},\n\t\"theming_configs\": {},\n\t\"meta\": \"meta\",\n\t\"external_key\": \"external-key\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/configs/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "configs", + "1", + "" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Routes API", + "item": [ + { + "name": "Get Routes", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/routes/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "routes", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get Route", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/routes/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "routes", + "1", + "" + ] + } + }, + "response": [] + }, + { + "name": "Create Route", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"domain\": \"domain\",\n\t\"config\": 1\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/routes/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "routes", + "" + ] + } + }, + "response": [] + }, + { + "name": "Delete Route", + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/routes/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "routes", + "1", + "" + ] + } + }, + "response": [] + }, + { + "name": "Update Route", + "request": { + "method": "PATCH", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n\t\"domain\": \"domain\",\n\t\"config\": 1\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{domain}}/eox-tenant/api/v1/routes/1/", + "host": [ + "{{domain}}" + ], + "path": [ + "eox-tenant", + "api", + "v1", + "routes", + "1", + "" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Authorization", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJson = pm.response.json();", + "var bodyToken = responseJson.access_token;", + "pm.environment.set(\"access_token\", bodyToken)", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "grant_type", + "value": "client_credentials", + "description": "Can be \"client_credentails\" or \"password\"", + "type": "text" + }, + { + "key": "token_type", + "value": "JWT", + "description": "Can be \"Bearer\" or \"JWT\"", + "type": "text" + }, + { + "key": "client_id", + "value": "", + "description": "The client ID of the application", + "type": "text" + }, + { + "key": "client_secret", + "value": "", + "description": "The client secret of the application", + "type": "text" + } + ] + }, + "url": { + "raw": "{{domain}}/oauth2/access_token", + "host": [ + "{{domain}}" + ], + "path": [ + "oauth2", + "access_token" + ] + } + }, + "response": [] + } + ], + "auth": { + "type": "oauth2", + "oauth2": [ + { + "key": "headerPrefix", + "value": "JWT", + "type": "string" + }, + { + "key": "addTokenTo", + "value": "header", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "domain", + "value": "http://local.edly.io:8000", + "type": "string" + } + ] +} \ No newline at end of file diff --git a/requirements/base.in b/requirements/base.in index 5e06a789..955cdab5 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -10,3 +10,4 @@ jsonfield edx-opaque-keys[django] openedx_filters social-auth-core +edx-drf-extensions diff --git a/requirements/base.txt b/requirements/base.txt index 66e335b2..d4d1c911 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,76 +4,119 @@ # # make upgrade # -asgiref==3.7.2 +asgiref==3.8.1 # via django backports-zoneinfo==0.2.1 - # via django + # via + # django + # djangorestframework certifi==2024.2.2 # via requests cffi==1.16.0 - # via cryptography + # via + # cryptography + # pynacl charset-normalizer==3.3.2 # via requests -cryptography==42.0.5 - # via social-auth-core +click==8.1.7 + # via edx-django-utils +cryptography==42.0.7 + # via + # pyjwt + # social-auth-core defusedxml==0.8.0rc2 # via # python3-openid # social-auth-core -django==4.2.11 +django==4.2.13 # via # -c requirements/constraints.txt # -r requirements/base.in # django-crum # django-mysql + # django-waffle # djangorestframework + # drf-jwt + # edx-django-utils + # edx-drf-extensions # jsonfield # openedx-filters django-crum==0.7.9 + # via + # -r requirements/base.in + # edx-django-utils +django-mysql==4.13.0 # via -r requirements/base.in -django-mysql==4.12.0 - # via -r requirements/base.in -djangorestframework==3.14.0 - # via -r requirements/base.in -edx-opaque-keys[django]==2.5.1 +django-waffle==4.1.0 + # via + # edx-django-utils + # edx-drf-extensions +djangorestframework==3.15.1 + # via + # -r requirements/base.in + # drf-jwt + # edx-drf-extensions +dnspython==2.6.1 + # via pymongo +drf-jwt==1.19.2 + # via edx-drf-extensions +edx-django-utils==5.14.1 + # via edx-drf-extensions +edx-drf-extensions==10.3.0 # via -r requirements/base.in -idna==3.6 +edx-opaque-keys[django]==2.9.0 + # via + # -r requirements/base.in + # edx-drf-extensions +idna==3.7 # via requests jsonfield==3.1.0 # via -r requirements/base.in +newrelic==9.10.0 + # via edx-django-utils oauthlib==3.2.2 # via # requests-oauthlib # social-auth-core -openedx-filters==1.6.0 +openedx-filters==1.8.1 # via -r requirements/base.in pbr==6.0.0 # via stevedore -pycparser==2.21 +psutil==5.9.8 + # via edx-django-utils +pycparser==2.22 # via cffi -pyjwt==2.8.0 - # via social-auth-core -pymongo==3.13.0 +pyjwt[crypto]==2.8.0 + # via + # drf-jwt + # edx-drf-extensions + # social-auth-core +pymongo==4.4.0 # via edx-opaque-keys +pynacl==1.5.0 + # via edx-django-utils python3-openid==3.2.0 # via social-auth-core -pytz==2024.1 - # via djangorestframework -requests==2.31.0 +requests==2.32.3 # via + # edx-drf-extensions # requests-oauthlib # social-auth-core -requests-oauthlib==1.3.1 +requests-oauthlib==2.0.0 # via social-auth-core +semantic-version==2.10.0 + # via edx-drf-extensions six==1.16.0 # via -r requirements/base.in -social-auth-core==4.5.3 +social-auth-core==4.5.4 # via -r requirements/base.in -sqlparse==0.4.4 +sqlparse==0.5.0 # via django stevedore==5.2.0 - # via edx-opaque-keys -typing-extensions==4.10.0 + # via + # edx-django-utils + # edx-opaque-keys +typing-extensions==4.12.0 # via # asgiref # edx-opaque-keys diff --git a/requirements/django42.txt b/requirements/django42.txt index db03776f..092a8ec1 100644 --- a/requirements/django42.txt +++ b/requirements/django42.txt @@ -1 +1 @@ -django==4.2.11 +django==4.2.13 diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index 8528adba..8460d793 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -4,17 +4,17 @@ # # make upgrade # -build==1.1.1 +build==1.2.1 # via pip-tools click==8.1.7 # via pip-tools -importlib-metadata==7.0.1 +importlib-metadata==7.1.0 # via build -packaging==23.2 +packaging==24.0 # via build -pip-tools==7.4.0 +pip-tools==7.4.1 # via -r requirements/pip-tools.in -pyproject-hooks==1.0.0 +pyproject-hooks==1.1.0 # via # build # pip-tools @@ -22,10 +22,9 @@ tomli==2.0.1 # via # build # pip-tools - # pyproject-hooks -wheel==0.42.0 +wheel==0.43.0 # via pip-tools -zipp==3.17.0 +zipp==3.19.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/test.txt b/requirements/test.txt index 585c8651..16df1c41 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -4,16 +4,17 @@ # # make upgrade # -asgiref==3.7.2 +asgiref==3.8.1 # via # -r requirements/base.txt # django -astroid==3.1.0 +astroid==3.2.2 # via pylint backports-zoneinfo==0.2.1 # via # -r requirements/base.txt # django + # djangorestframework certifi==2024.2.2 # via # -r requirements/base.txt @@ -22,15 +23,21 @@ cffi==1.16.0 # via # -r requirements/base.txt # cryptography + # pynacl charset-normalizer==3.3.2 # via # -r requirements/base.txt # requests -coverage==7.4.3 +click==8.1.7 + # via + # -r requirements/base.txt + # edx-django-utils +coverage==7.5.3 # via -r requirements/test.in -cryptography==42.0.5 +cryptography==42.0.7 # via # -r requirements/base.txt + # pyjwt # social-auth-core ddt==1.7.2 # via -r requirements/test.in @@ -46,22 +53,50 @@ dill==0.3.8 # -r requirements/base.txt # django-crum # django-mysql + # django-waffle # djangorestframework + # drf-jwt + # edx-django-utils + # edx-drf-extensions # jsonfield # openedx-filters django-crum==0.7.9 - # via -r requirements/base.txt + # via + # -r requirements/base.txt + # edx-django-utils django-fake-model==0.1.4 # via -r requirements/test.in -django-mysql==4.12.0 +django-mysql==4.13.0 # via -r requirements/base.txt -djangorestframework==3.14.0 +django-waffle==4.1.0 + # via + # -r requirements/base.txt + # edx-django-utils + # edx-drf-extensions +djangorestframework==3.15.1 + # via + # -r requirements/base.txt + # drf-jwt + # edx-drf-extensions +dnspython==2.6.1 + # via + # -r requirements/base.txt + # pymongo +drf-jwt==1.19.2 + # via + # -r requirements/base.txt + # edx-drf-extensions +edx-django-utils==5.14.1 + # via + # -r requirements/base.txt + # edx-drf-extensions +edx-drf-extensions==10.3.0 # via -r requirements/base.txt -edx-opaque-keys[django]==2.5.1 +edx-opaque-keys[django]==2.9.0 # via # -r requirements/base.txt - # edx-opaque-keys -idna==3.6 + # edx-drf-extensions +idna==3.7 # via # -r requirements/base.txt # requests @@ -73,14 +108,18 @@ mccabe==0.7.0 # via pylint mock==5.1.0 # via -r requirements/test.in +newrelic==9.10.0 + # via + # -r requirements/base.txt + # edx-django-utils oauthlib==3.2.2 # via # -r requirements/base.txt # requests-oauthlib # social-auth-core -openedx-filters==1.6.0 +openedx-filters==1.8.1 # via -r requirements/base.txt -path==16.10.0 +path==16.14.0 # via path-py path-py==12.5.0 # via -r requirements/test.in @@ -88,62 +127,74 @@ pbr==6.0.0 # via # -r requirements/base.txt # stevedore -platformdirs==4.2.0 +platformdirs==4.2.2 # via pylint +psutil==5.9.8 + # via + # -r requirements/base.txt + # edx-django-utils pycodestyle==2.11.1 # via -r requirements/test.in -pycparser==2.21 +pycparser==2.22 # via # -r requirements/base.txt # cffi -pyjwt==2.8.0 +pyjwt[crypto]==2.8.0 # via # -r requirements/base.txt + # drf-jwt + # edx-drf-extensions # social-auth-core -pylint==3.1.0 +pylint==3.2.2 # via -r requirements/test.in -pymongo==3.13.0 +pymongo==4.4.0 # via # -r requirements/base.txt # edx-opaque-keys -pyyaml==6.0.1 - # via -r requirements/test.in -python3-openid==3.2.0 +pynacl==1.5.0 # via # -r requirements/base.txt - # social-auth-core -pytz==2024.1 + # edx-django-utils +python3-openid==3.2.0 # via # -r requirements/base.txt - # djangorestframework -requests==2.31.0 + # social-auth-core +pyyaml==6.0.1 + # via -r requirements/test.in +requests==2.32.3 # via # -r requirements/base.txt + # edx-drf-extensions # requests-oauthlib # social-auth-core -requests-oauthlib==1.3.1 +requests-oauthlib==2.0.0 # via # -r requirements/base.txt # social-auth-core +semantic-version==2.10.0 + # via + # -r requirements/base.txt + # edx-drf-extensions six==1.16.0 # via -r requirements/base.txt -social-auth-core==4.5.3 +social-auth-core==4.5.4 # via -r requirements/base.txt -sqlparse==0.4.4 +sqlparse==0.5.0 # via # -r requirements/base.txt # django stevedore==5.2.0 # via # -r requirements/base.txt + # edx-django-utils # edx-opaque-keys -testfixtures==8.1.0 +testfixtures==8.2.0 # via -r requirements/test.in tomli==2.0.1 # via pylint -tomlkit==0.12.4 +tomlkit==0.12.5 # via pylint -typing-extensions==4.10.0 +typing-extensions==4.12.0 # via # -r requirements/base.txt # asgiref diff --git a/requirements/tox.txt b/requirements/tox.txt index e9a64909..b38db655 100644 --- a/requirements/tox.txt +++ b/requirements/tox.txt @@ -12,19 +12,19 @@ colorama==0.4.6 # via tox distlib==0.3.8 # via virtualenv -filelock==3.13.1 +filelock==3.14.0 # via # tox # virtualenv -packaging==23.2 +packaging==24.0 # via # pyproject-api # tox -platformdirs==4.2.0 +platformdirs==4.2.2 # via # tox # virtualenv -pluggy==1.4.0 +pluggy==1.5.0 # via tox pyproject-api==1.6.1 # via tox @@ -32,7 +32,7 @@ tomli==2.0.1 # via # pyproject-api # tox -tox==4.13.0 +tox==4.15.0 # via -r requirements/tox.in -virtualenv==20.25.1 +virtualenv==20.26.2 # via tox