diff --git a/api/app/backend/settings.py b/api/app/backend/settings.py index e7df930..93512cf 100644 --- a/api/app/backend/settings.py +++ b/api/app/backend/settings.py @@ -40,7 +40,8 @@ INSTALLED_APPS = [ 'rest_framework.authtoken', "rest_framework", "snippets", - "custom_auth" + "custom_auth", + 'rest_framework_simplejwt' ] MIDDLEWARE = [ @@ -136,3 +137,13 @@ AUTH_PASSWORD_VALIDATORS = {} CORS_ALLOWED_ORIGINS = [ "*" ] + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework_simplejwt.authentication.JWTAuthentication', + ) +} + +SIMPLE_JWT = { + "TOKEN_OBTAIN_SERIALIZER": "custom_auth.serializers.MyTokenObtainPairSerializer", +} diff --git a/api/app/custom_auth/serializers.py b/api/app/custom_auth/serializers.py new file mode 100644 index 0000000..6d7be40 --- /dev/null +++ b/api/app/custom_auth/serializers.py @@ -0,0 +1,9 @@ +from rest_framework_simplejwt.serializers import TokenObtainPairSerializer +from rest_framework_simplejwt.views import TokenObtainPairView + +class MyTokenObtainPairSerializer(TokenObtainPairSerializer): + @classmethod + def get_token(cls, user): + token = super().get_token(user) + token['username'] = user.username + return token diff --git a/api/app/custom_auth/urls.py b/api/app/custom_auth/urls.py index 2f21f6c..043f71c 100644 --- a/api/app/custom_auth/urls.py +++ b/api/app/custom_auth/urls.py @@ -1,8 +1,16 @@ from django.urls import path, include from custom_auth import views +from rest_framework_simplejwt.views import ( + TokenObtainPairView, + TokenRefreshView, + TokenVerifyView, +) urlpatterns = [ path('', include('rest_framework.urls')), - path('token/', views.CustomAuthToken.as_view()), - path('register/', views.RegisterView.as_view()) + # path('token/', views.CustomAuthToken.as_view()), + path('register/', views.RegisterView.as_view()), + path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('token/verify/', TokenVerifyView.as_view(), name='token_verify'), ] diff --git a/api/app/custom_auth/views.py b/api/app/custom_auth/views.py index 45d3b9d..6bef543 100644 --- a/api/app/custom_auth/views.py +++ b/api/app/custom_auth/views.py @@ -4,6 +4,7 @@ from rest_framework.response import Response from rest_framework.request import Request from rest_framework.views import APIView from django.contrib.auth.models import User +from rest_framework_simplejwt.tokens import RefreshToken class CustomAuthToken(ObtainAuthToken): @@ -12,12 +13,19 @@ class CustomAuthToken(ObtainAuthToken): context={'request': request}) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] - token, created = Token.objects.get_or_create(user=user) - return Response({ - 'token': token.key, - 'user_id': user.pk, - 'username': user.username - }) + refresh = RefreshToken.for_user(user) + + return { + 'refresh': str(refresh), + 'access': str(refresh.access_token), + } + # + # token, created = Token.objects.get_or_create(user=user) + # return Response({ + # 'token': token.key, + # 'user_id': user.pk, + # 'username': user.username + # }) class RegisterView(APIView): @@ -45,11 +53,16 @@ class RegisterView(APIView): username=username, password=password ) - token, created = Token.objects.get_or_create(user=user) - return Response({ - 'token': token.key, - 'user_id': user.pk, - 'username': user.username - }, status=200) + refresh = RefreshToken.for_user(user) + return { + 'refresh': str(refresh), + 'access': str(refresh.access_token), + } + # token, created = Token.objects.get_or_create(user=user) + # return Response({ + # 'token': token.key, + # 'user_id': user.pk, + # 'username': user.username + # }, status=200) except Exception as e: return Response({"message": "Something went wrong, registration is not completed", "error": e}, status=500) diff --git a/api/requirements.txt b/api/requirements.txt index 65adb29..47b7e2c 100644 --- a/api/requirements.txt +++ b/api/requirements.txt @@ -1,4 +1,5 @@ django django-rest-framework django-cors-headers +djangorestframework-simplejwt pygments diff --git a/docker-compose.yml b/docker-compose.yml index 3ab7a6a..41e2257 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,8 +16,9 @@ services: - "3000" environment: - WDS_SOCKET_PORT=0 - # volumes: - # - ./docker_cache/node_modules:/app/node_modules + volumes: + - ./react/app:/app:z + # - ./docker_cache/node_modules:/app/node_modules nginx: image: nginx:1.23.4 volumes: diff --git a/react/app/src/components/Header.jsx b/react/app/src/components/Header.jsx index 48034d7..5db63f5 100644 --- a/react/app/src/components/Header.jsx +++ b/react/app/src/components/Header.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useContext } from 'react'; import { MDBContainer, MDBNavbar, @@ -18,9 +18,11 @@ import { import 'mdb-react-ui-kit/dist/css/mdb.min.css'; import "@fortawesome/fontawesome-free/css/all.min.css"; import { Link } from 'react-router-dom'; +import AuthContext from "../context/AuthContext"; export default function App() { const [showBasic, setShowBasic] = useState(false); + const { user } = useContext(AuthContext); return ( @@ -46,7 +48,7 @@ export default function App() { - Link + News @@ -57,22 +59,26 @@ export default function App() { Public snippets My snippets - Something else here + Shared to me snippets - + New snippet - - - admin - - + + { user && ( + + + {user?.username} + + + )} + diff --git a/react/app/src/context/AuthContext.jsx b/react/app/src/context/AuthContext.jsx index bea4611..cffa519 100644 --- a/react/app/src/context/AuthContext.jsx +++ b/react/app/src/context/AuthContext.jsx @@ -2,7 +2,7 @@ import { createContext, useState, useEffect } from "react"; import jwt_decode from "jwt-decode"; import { useNavigate } from "react-router-dom"; -const AuthContext = createContext(""); +const AuthContext = createContext(); export default AuthContext; @@ -25,8 +25,7 @@ export const AuthProvider = ({ children }) => { const response = await fetch("http://127.0.0.1/api/auth/token/", { method: "POST", headers: { - "Content-Type": "application/json", - "Access-Control-Allow-Origin": "*", + "Content-Type": "application/json" }, body: JSON.stringify({ username, @@ -36,30 +35,29 @@ export const AuthProvider = ({ children }) => { const data = await response.json(); if (response.status === 200) { - console.log(response, data) setAuthTokens(data); setUser(jwt_decode(data.access)); localStorage.setItem("authTokens", JSON.stringify(data)); - history.push("/"); + history("/"); } else { alert("Something went wrong!"); } }; - const registerUser = async (username, password) => { + const registerUser = async (username, password, password2) => { const response = await fetch("http://127.0.0.1/api/auth/register/", { method: "POST", headers: { - "Content-Type": "application/json", - "Access-Control-Allow-Origin": "*", + "Content-Type": "application/json" }, body: JSON.stringify({ username, - password + password, + password2 }) }); if (response.status === 201) { - history.push("/login"); + history("/login"); } else { alert("Something went wrong!"); } @@ -69,7 +67,7 @@ export const AuthProvider = ({ children }) => { setAuthTokens(null); setUser(null); localStorage.removeItem("authTokens"); - history.push("/"); + history("/"); }; const contextData = {