handle logout, #855

This commit is contained in:
Simon
2025-01-01 15:26:23 +07:00
parent 20e3b7b7ff
commit 86232b8628
5 changed files with 47 additions and 5 deletions

View File

@@ -5,5 +5,6 @@ from user import views
urlpatterns = [ urlpatterns = [
path("login/", views.LoginApiView.as_view(), name="api-user-login"), path("login/", views.LoginApiView.as_view(), name="api-user-login"),
path("logout/", views.LogoutApiView.as_view(), name="api-user-logout"),
path("me/", views.UserConfigView.as_view(), name="api-user-me"), path("me/", views.UserConfigView.as_view(), name="api-user-me"),
] ]

View File

@@ -1,7 +1,7 @@
"""all user api views""" """all user api views"""
from common.views import ApiBaseView from common.views import ApiBaseView
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login, logout
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from rest_framework.permissions import AllowAny from rest_framework.permissions import AllowAny
@@ -82,3 +82,14 @@ class LoginApiView(APIView):
return Response({"message": "Login successful"}, status=200) return Response({"message": "Login successful"}, status=200)
return Response({"message": "Invalid credentials"}, status=400) return Response({"message": "Invalid credentials"}, status=400)
class LogoutApiView(ApiBaseView):
"""resolves to /api/user/logout/
POST: handle logout
"""
def post(self, request, *args, **kwargs):
"""logout on post request"""
logout(request)
return Response({"message": "Successfully logged out."}, status=200)

View File

@@ -0,0 +1,22 @@
import defaultHeaders from '../../configuration/defaultHeaders';
import getApiUrl from "../../configuration/getApiUrl"
import getFetchCredentials from "../../configuration/getFetchCredentials";
import getCookie from "../../functions/getCookie";
const logOut = async () => {
const apiUrl = getApiUrl();
const csrfCookie = getCookie('csrftoken');
const response = await fetch(`${apiUrl}/api/user/logout/`, {
method: 'POST',
headers: {
...defaultHeaders,
'X-CSRFToken': csrfCookie || '',
},
credentials: getFetchCredentials(),
})
return response;
}
export default logOut;

View File

@@ -1,15 +1,24 @@
import { Link } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import iconSearch from '/img/icon-search.svg'; import iconSearch from '/img/icon-search.svg';
import iconGear from '/img/icon-gear.svg'; import iconGear from '/img/icon-gear.svg';
import iconExit from '/img/icon-exit.svg'; import iconExit from '/img/icon-exit.svg';
import Routes from '../configuration/routes/RouteList'; import Routes from '../configuration/routes/RouteList';
import NavigationItem from './NavigationItem'; import NavigationItem from './NavigationItem';
import logOut from '../api/actions/logOut';
interface NavigationProps { interface NavigationProps {
isAdmin: boolean; isAdmin: boolean;
} }
const Navigation = ({ isAdmin }: NavigationProps) => { const Navigation = ({ isAdmin }: NavigationProps) => {
const navigate = useNavigate();
const handleLogout = async (event: { preventDefault: () => void }) => {
event.preventDefault();
await logOut();
navigate(Routes.Login)
}
return ( return (
<div className="boxed-content"> <div className="boxed-content">
<Link to={Routes.Home}> <Link to={Routes.Home}>
@@ -30,9 +39,7 @@ const Navigation = ({ isAdmin }: NavigationProps) => {
<Link to={Routes.SettingsDashboard}> <Link to={Routes.SettingsDashboard}>
<img src={iconGear} alt="gear-icon" title="Settings" /> <img src={iconGear} alt="gear-icon" title="Settings" />
</Link> </Link>
<Link to={Routes.Logout}> <img className="alert-hover" src={iconExit} alt="exit-icon" title="Logout" onClick={handleLogout} />
<img className="alert-hover" src={iconExit} alt="exit-icon" title="Logout" />
</Link>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -319,6 +319,7 @@ button:hover {
.alert-hover:hover { .alert-hover:hover {
filter: var(--img-filter-error); filter: var(--img-filter-error);
cursor: pointer;
} }
/* top of page */ /* top of page */