167 lines
6.4 KiB
Python
167 lines
6.4 KiB
Python
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 |