From 048c8927b839f272574093ac5b21dc3f5d8fea5e Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 18 May 2021 12:07:03 +0200 Subject: [PATCH] refactor: Remove djoser dependency --- requirements.txt | 5 ++- src/api.ts | 47 +++++++++++++++++++++++------ userausfall/rest_api/serializers.py | 21 +++---------- userausfall/rest_api/urls.py | 4 +-- userausfall/rest_api/views.py | 20 +++++++++--- userausfall/settings.py | 16 +--------- userausfall/urls.py | 3 +- 7 files changed, 62 insertions(+), 54 deletions(-) diff --git a/requirements.txt b/requirements.txt index 95e08be..906b98f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -setuptools~=56.0.0 +setuptools~=40.8.0 django~=2.2.13 -djangorestframework~=3.12.4 -djoser~=2.1.0 +djangorestframework~=3.9.0 \ No newline at end of file diff --git a/src/api.ts b/src/api.ts index 5c8f047..ef72ad6 100644 --- a/src/api.ts +++ b/src/api.ts @@ -29,7 +29,7 @@ async function request( } init.headers.set("Accept", "application/json"); init.headers.set("Content-Type", "application/json"); - const response = await fetch(`/api/${endpoint}/`, init); + const response = await fetch(`/${endpoint}/`, init); if (response.status !== 204) { if (response.status === successStatus) { return await response.json(); @@ -39,6 +39,16 @@ async function request( } } +async function api_request( + method: HTTPMethod, + endpoint: string, + successStatus: number, + data: any, + authToken?: string +) { + return request(method, `api/${endpoint}`, successStatus, data, authToken); +} + export class User { email: string | undefined; password: string | undefined; @@ -48,20 +58,37 @@ export class User { private token = ""; static async confirm(uid: string, token: string): Promise { - await request("POST", "users/activation", 204, { uid, token }); + await api_request("POST", "users/activation", 204, { uid, token }); } async login(): Promise { - const response = await request("POST", "token/login", 200, { - email: this.email, - password: this.password, - }); - this.token = response.auth_token; - this.isAuthenticated = true; + if (!this.email || !this.password) throw new APIError("", ""); + + // logout any existing sessions + //await logout() + // fetch the login endpoint we use for authentication + const loginEndpoint = "/api-auth/login/"; + // fetch the login page, so it sets csrf cookies + await window.fetch(loginEndpoint); + + // authenticate us + const body = new window.FormData(); + body.append("username", this.email); + body.append("password", this.password); + const csrf_token = Cookies.get("csrftoken"); + if (csrf_token) body.append("csrfmiddlewaretoken", csrf_token); + const res = await window.fetch(loginEndpoint, { method: "post", body }); + + // successful logins are followed by a redirect + if (res.redirected && res.status === 200) { + this.isAuthenticated = true; + } else { + throw new APIError("", ""); + } } async save(): Promise { - await request( + await api_request( "PATCH", "users/me", 200, @@ -74,7 +101,7 @@ export class User { } async signup(): Promise { - await request("POST", "users", 201, { + await api_request("POST", "users", 201, { email: this.email, password: this.password, }); diff --git a/userausfall/rest_api/serializers.py b/userausfall/rest_api/serializers.py index 6d20bd8..97ced7b 100644 --- a/userausfall/rest_api/serializers.py +++ b/userausfall/rest_api/serializers.py @@ -1,26 +1,13 @@ -from djoser.serializers import UserSerializer as BaseUserSerializer from rest_framework import serializers -from userausfall.models import AccountRequest +from userausfall.models import AccountRequest, User -class AccountRequestSerializer(serializers.HyperlinkedModelSerializer): - class Meta: - model = AccountRequest - fields = ( - "url", - "email", - "confidant_email", - "username", - "is_verified", - "is_trustable", - ) - - -class UserSerializer(BaseUserSerializer): +class UserSerializer(serializers.ModelSerializer): confidant_email = serializers.EmailField(source="get_confidant_email") - class Meta(BaseUserSerializer.Meta): + class Meta: + model = User fields = ("email", "username", "confidant_email") def get_confidant_email(self): diff --git a/userausfall/rest_api/urls.py b/userausfall/rest_api/urls.py index 4c9629f..3094cd0 100644 --- a/userausfall/rest_api/urls.py +++ b/userausfall/rest_api/urls.py @@ -1,6 +1,6 @@ from rest_framework import routers -from userausfall.rest_api.views import AccountRequestViewSet +from userausfall.rest_api.views import UserViewSet router = routers.DefaultRouter(trailing_slash=True) -router.register(r'account_requests', AccountRequestViewSet) +router.register(r'users', UserViewSet, basename="user") diff --git a/userausfall/rest_api/views.py b/userausfall/rest_api/views.py index 7a269f7..c2ff3d6 100644 --- a/userausfall/rest_api/views.py +++ b/userausfall/rest_api/views.py @@ -1,9 +1,19 @@ from rest_framework import viewsets +from rest_framework.decorators import action +from rest_framework.response import Response -from userausfall.models import AccountRequest -from userausfall.rest_api.serializers import AccountRequestSerializer +from userausfall.models import User +from userausfall.rest_api.serializers import UserSerializer -class AccountRequestViewSet(viewsets.ModelViewSet): - serializer_class = AccountRequestSerializer - queryset = AccountRequest.objects.all() +class UserViewSet(viewsets.ModelViewSet): + class Meta: + queryset = User.objects.all() + + @action(detail=False, methods=["PATCH"]) + def me(self, request): + return Response( + UserSerializer( + instance=request.user, context={"request": request} + ).data + ) diff --git a/userausfall/settings.py b/userausfall/settings.py index c23b8bf..1815e91 100644 --- a/userausfall/settings.py +++ b/userausfall/settings.py @@ -38,8 +38,6 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'userausfall', 'rest_framework', - 'rest_framework.authtoken', - 'djoser', ] MIDDLEWARE = [ @@ -137,18 +135,6 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/' -# Djoser settings -# https://djoser.readthedocs.io/en/2.1.0/settings.html - -DJOSER = { - "ACTIVATION_URL": "confirm/{uid}/{token}", - "SEND_ACTIVATION_EMAIL": True, - "SERIALIZERS": { - "current_user": "userausfall.rest_api.serializers.UserSerializer", - } -} - - # Sending email # https://docs.djangoproject.com/en/3.2/topics/email/ @@ -160,6 +146,6 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework.authentication.TokenAuthentication', + 'rest_framework.authentication.SessionAuthentication', ), } diff --git a/userausfall/urls.py b/userausfall/urls.py index b353d4b..0175b96 100644 --- a/userausfall/urls.py +++ b/userausfall/urls.py @@ -6,6 +6,5 @@ from userausfall.rest_api import urls as rest_api_urls urlpatterns = [ path('admin/', admin.site.urls), path('api/', include(rest_api_urls.router.urls)), - path('api/', include('djoser.urls')), - path('api/', include('djoser.urls.authtoken')), + path("api-auth/", include("rest_framework.urls")), ]