From e05319ec3c5a3f0db0884d630031415dd0552f90 Mon Sep 17 00:00:00 2001 From: MOIS3Y Date: Sat, 12 Aug 2023 18:17:40 +0900 Subject: [PATCH] Add: jwt auth endpoints --- logs_collector/collector/urls.py | 2 +- logs_collector/logs_collector/settings.py | 63 +++++++++++++++++++++-- logs_collector/logs_collector/urls.py | 32 ++++++++++-- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/logs_collector/collector/urls.py b/logs_collector/collector/urls.py index 485690c..e4f8aae 100644 --- a/logs_collector/collector/urls.py +++ b/logs_collector/collector/urls.py @@ -78,5 +78,5 @@ urlpatterns = [ # -- -- -- # CRUD: - path('api/v1/', include(router.urls)) + path('api/v1/', include(router.urls)), ] diff --git a/logs_collector/logs_collector/settings.py b/logs_collector/logs_collector/settings.py index ad7574d..d10fa07 100644 --- a/logs_collector/logs_collector/settings.py +++ b/logs_collector/logs_collector/settings.py @@ -1,10 +1,12 @@ import environ from pathlib import Path +from datetime import timedelta env = environ.Env( # set casting default value - DEBUG=(bool, False) + DEBUG=(bool, False), + SECRET_KEY=(str, 'j9QGbvM9Z4otb47') ) # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -35,6 +37,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'collector.apps.CollectorConfig', # main app 'rest_framework', + 'rest_framework_simplejwt', 'django_filters', 'drf_spectacular', "crispy_forms", @@ -108,7 +111,7 @@ AUTH_PASSWORD_VALIDATORS = [ LANGUAGE_CODE = 'en-us' -TIME_ZONE = 'Asia/Irkutsk' +TIME_ZONE = env('TZ', default='UTC') USE_I18N = True @@ -139,6 +142,7 @@ CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" CRISPY_TEMPLATE_PACK = "bootstrap5" # https://www.django-rest-framework.org/api-guide/settings/ + REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', @@ -149,6 +153,11 @@ REST_FRAMEWORK = { 'rest_framework.renderers.BrowsableAPIRenderer', 'rest_framework.parsers.MultiPartParser' ], + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework_simplejwt.authentication.JWTAuthentication', + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.BasicAuthentication' + ], 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend', ], # noqa:E501 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', # noqa:E501 @@ -157,11 +166,59 @@ REST_FRAMEWORK = { # https://drf-spectacular.readthedocs.io/en/latest/readme.html # TODO: set environ vars config! + SPECTACULAR_SETTINGS = { 'TITLE': 'Logs collector API', 'DESCRIPTION': 'Collector of archives with log files for further analysis', 'VERSION': '0.1.0', 'SERVE_INCLUDE_SCHEMA': True, 'SERVE_PUBLIC': False, - 'SERVERS': [{'url': 'https://example.com/v1', 'description': 'Text'},], + 'SERVERS': [ + { + 'url': 'http://localhost:8000/api/v1/', + 'description': 'main api endpoint' + }, + ], +} + +# https://django-rest-framework-simplejwt.readthedocs.io/en/latest/ + +SIMPLE_JWT = { + "ACCESS_TOKEN_LIFETIME": timedelta(minutes=60), + "REFRESH_TOKEN_LIFETIME": timedelta(days=1), + "ROTATE_REFRESH_TOKENS": False, + "BLACKLIST_AFTER_ROTATION": False, + "UPDATE_LAST_LOGIN": False, + + "ALGORITHM": "HS256", + "SIGNING_KEY": SECRET_KEY, + "VERIFYING_KEY": "", + "AUDIENCE": None, + "ISSUER": None, + "JSON_ENCODER": None, + "JWK_URL": None, + "LEEWAY": 0, + + "AUTH_HEADER_TYPES": ("Bearer",), + "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION", + "USER_ID_FIELD": "id", + "USER_ID_CLAIM": "user_id", + "USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule", # noqa:E501 + + "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",), + "TOKEN_TYPE_CLAIM": "token_type", + "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser", + + "JTI_CLAIM": "jti", + + "SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp", + "SLIDING_TOKEN_LIFETIME": timedelta(minutes=5), + "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1), + + "TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer", # noqa:E501 + "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer", # noqa:E501 + "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer", # noqa:E501 + "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer", # noqa:E501 + "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer", # noqa:E501 + "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer", # noqa:E501 } diff --git a/logs_collector/logs_collector/urls.py b/logs_collector/logs_collector/urls.py index b616069..3d237e2 100644 --- a/logs_collector/logs_collector/urls.py +++ b/logs_collector/logs_collector/urls.py @@ -18,13 +18,18 @@ from django.conf.urls.static import static from django.contrib import admin from django.urls import path, include +from rest_framework_simplejwt.views import ( + TokenObtainPairView, + TokenRefreshView, + TokenVerifyView +) + from drf_spectacular.views import ( SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView ) - from logs_collector import settings @@ -33,17 +38,36 @@ urlpatterns = [ path('', include('collector.urls', namespace='collector')), ] +urlpatterns += [ + # JWT AUTH: + path( + 'api/v1/auth/token/', + TokenObtainPairView.as_view(), + name='token_obtain_pair' + ), + path( + 'api/v1/auth/token/refresh/', + TokenRefreshView.as_view(), + name='token_refresh' + ), + path( + 'api/v1/auth/token/verify/', + TokenVerifyView.as_view(), + name='token_verify' + ), +] + urlpatterns += [ # API PATTERNS - path('api/schema/', SpectacularAPIView.as_view(), name='schema'), + path('api/v1/schema/', SpectacularAPIView.as_view(), name='schema'), # Optional UI: path( - 'api/schema/swagger-ui/', + 'api/v1/schema/swagger/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui' ), path( - 'api/schema/redoc/', + 'api/v1/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc' ),