login route

This commit is contained in:
Timofey
2025-08-29 14:44:26 +03:00
parent d314303066
commit 5a06a625fb
11 changed files with 701 additions and 5 deletions

View File

@@ -0,0 +1,167 @@
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.views import APIView
from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiExample
from drf_spectacular.types import OpenApiTypes
from django.contrib.auth.models import User
from .serializers import (
UserResponseSerializer,
LoginRequestSerializer,
LoginResponseSerializer
)
from api.utils.cookies import AuthBaseViewSet
from api.types import User
class LoginViewSet(AuthBaseViewSet):
"""ViewSet для авторизации пользователей"""
serializer_class = LoginRequestSerializer
@extend_schema(
summary="Авторизация пользователя",
description="Эндпоинт для авторизации пользователя по логину и паролю",
request=LoginRequestSerializer,
responses={
200: OpenApiResponse(
response=LoginResponseSerializer,
description="Успешная авторизация",
examples=[
OpenApiExample(
'Успешный ответ',
value={
"message": "Успешная авторизация",
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": 1,
"email": "user@example.com",
"account_type": "engieneer",
"name": "Иван",
"surname": "Иванов",
"imageURL": "https://example.com/avatar.jpg",
"uuid": "abc123"
}
}
)
]
),
400: OpenApiResponse(
description="Неверные параметры запроса",
response=OpenApiTypes.OBJECT,
examples=[
OpenApiExample(
'Отсутствуют обязательные поля',
value={"error": "Логин и пароль обязательны"}
)
]
),
403: OpenApiResponse(
description="Неверный пароль",
response=OpenApiTypes.OBJECT,
examples=[
OpenApiExample(
'Неверный пароль',
value={"error": "Неверный пароль"}
)
]
),
404: OpenApiResponse(
description="Пользователь не найден",
response=OpenApiTypes.OBJECT,
examples=[
OpenApiExample(
'Пользователь не найден',
value={"error": "Пользователь не найден"}
)
]
),
500: OpenApiResponse(
description="Внутренняя ошибка сервера",
response=OpenApiTypes.OBJECT,
examples=[
OpenApiExample(
'Ошибка сервера',
value={"error": "Ошибка авторизации"}
)
]
)
}
)
@action(detail=False, methods=['post'], url_path="login")
def login_client(self, request):
try:
login = request.data.get("login")
password = request.data.get("password")
if not login or not password:
return Response(
{"error": "Логин и пароль обязательны"},
status=status.HTTP_400_BAD_REQUEST
)
try:
user = User.objects.get(login=login)
except User.DoesNotExist:
return Response(
{"error": "Пользователь не найден"},
status=status.HTTP_404_NOT_FOUND
)
if not user.check_password(password):
return Response(
{"error": "Неверный пароль"},
status=status.HTTP_403_FORBIDDEN
)
refresh = RefreshToken.for_user(user)
user_data = UserResponseSerializer(user).data
response = Response({
"message": "Успешная авторизация",
"access": str(refresh.access_token),
"refresh": str(refresh),
"user": user_data
}, status=status.HTTP_200_OK)
# сеттим куки
return self._set_auth_cookies(response, refresh)
except Exception as e:
return Response(
{"error": "Ошибка авторизации"},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
class LogoutView(APIView):
"""ViewSet для выхода из системы"""
@extend_schema(
summary="Выход из системы",
description="Эндпоинт для выхода из системы, очищает все токены и куки",
responses={
200: OpenApiResponse(
description="Успешный выход",
response=OpenApiTypes.OBJECT,
examples=[
OpenApiExample(
'Успешный выход',
value={"message": "Logged out"}
)
]
)
}
)
def post(self, request):
response = Response({'message': 'Logged out'}, status=status.HTTP_200_OK)
# чистим куки и sessionID
response.delete_cookie('access_token')
response.delete_cookie('refresh_token')
response.delete_cookie('sessionid')
return response