diff --git a/backend/get_api_token.http b/backend/get_api_token.http new file mode 100644 index 0000000..250c6ed --- /dev/null +++ b/backend/get_api_token.http @@ -0,0 +1,13 @@ +OPTIONS http://127.0.0.1:30033/api/auth/token/ + +### + +POST http://127.0.0.1:30033/api/auth/token/ +Content-Type: application/json + +{ + "username": "", + "password": "" +} + +### diff --git a/backend/sophon/auth1.py b/backend/sophon/auth1.py new file mode 100644 index 0000000..6f9e93c --- /dev/null +++ b/backend/sophon/auth1.py @@ -0,0 +1,9 @@ +import rest_framework.authentication + + +class BearerTokenAuthentication(rest_framework.authentication.TokenAuthentication): + """ + A standard implementation of the Token Authentication. + """ + + keyword = "Bearer" diff --git a/backend/sophon/auth2.py b/backend/sophon/auth2.py new file mode 100644 index 0000000..58f4281 --- /dev/null +++ b/backend/sophon/auth2.py @@ -0,0 +1,26 @@ +# why is this needed? +# django somehow import-cycles itself if i put this in auth1 + +import rest_framework.authtoken.views +import rest_framework.authtoken.models +import rest_framework.response + + +class CustomObtainAuthToken(rest_framework.authtoken.views.ObtainAuthToken): + def post(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + user = serializer.validated_data['user'] + token, created = rest_framework.authtoken.models.Token.objects.get_or_create(user=user) + return rest_framework.response.Response({ + 'token': token.key, + 'user': { + 'id': user.pk, + 'username': user.username, + 'email': user.email, + 'first_name': user.first_name, + 'last_name': user.last_name, + 'is_staff': user.is_staff, + 'is_superuser': user.is_superuser, + }, + }) diff --git a/backend/sophon/settings.py b/backend/sophon/settings.py index 9bba151..4c315c2 100644 --- a/backend/sophon/settings.py +++ b/backend/sophon/settings.py @@ -14,6 +14,8 @@ import os from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. +import rest_framework.authentication + BASE_DIR = Path(__file__).resolve().parent.parent @@ -40,6 +42,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'django.contrib.postgres', 'rest_framework', + 'rest_framework.authtoken', 'colorfield', 'sophon.core', # FIXME: Is .apps.CoreConfig not needed? ] @@ -141,6 +144,7 @@ STATIC_URL = '/static/' # Django REST framework # https://www.django-rest-framework.org/#example + REST_FRAMEWORK = { # Use Django's standard `django.contrib.auth` permissions, # or allow read-only access for unauthenticated users. @@ -148,6 +152,11 @@ REST_FRAMEWORK = { 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' ], 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.BasicAuthentication', + 'rest_framework.authentication.SessionAuthentication', + 'sophon.auth1.BearerTokenAuthentication', + ], 'PAGE_SIZE': 100, } diff --git a/backend/sophon/urls.py b/backend/sophon/urls.py index a363f0d..ad618a1 100644 --- a/backend/sophon/urls.py +++ b/backend/sophon/urls.py @@ -15,9 +15,11 @@ Including another URLconf """ from django.contrib import admin from django.urls import path, include +from .auth2 import CustomObtainAuthToken urlpatterns = [ path('admin/', admin.site.urls), - path('api-auth/', include("rest_framework.urls")), + path('api/auth/token/', CustomObtainAuthToken.as_view()), + path('api/auth/session/', include("rest_framework.urls")), path('api/', include("sophon.core.urls")), ]