register logic

This commit is contained in:
2025-05-18 13:37:27 +03:00
parent be46e09aeb
commit 695c29ab62
19 changed files with 498 additions and 36 deletions

View File

@@ -5,7 +5,7 @@ from django.db.utils import IntegrityError
from api.models import UserProfile
class UserResponceSerializer(serializers.Serializer):
class UserResponseSerializer(serializers.Serializer):
id = serializers.IntegerField()
email = serializers.EmailField()
name = serializers.CharField(source='first_name')
@@ -24,16 +24,17 @@ class ClientRegisterSerializer(serializers.ModelSerializer):
phone_number = serializers.CharField(max_length=13)
privacy_accepted = serializers.BooleanField()
email = serializers.EmailField(required=True)
username = serializers.CharField(source='first_name')
name = serializers.CharField(required=True)
surname = serializers.CharField(required=True)
uuid = serializers.SerializerMethodField()
class Meta:
model = User
fields = ['id', 'uuid', 'username', 'email', 'password', 'phone_number', 'privacy_accepted']
fields = ['id', 'uuid', 'name', 'surname', 'email', 'password', 'phone_number', 'privacy_accepted']
extra_kwargs = {
'password' : {'write_only':True},
'email' : {'required' : True, 'unique': True},
'phone_number' : {'required' : True, 'unique': True},
'password': {'write_only': True},
'email': {'required': True},
'phone_number': {'required': True},
}
def validate_phone_number(self, value):
@@ -44,18 +45,21 @@ class ClientRegisterSerializer(serializers.ModelSerializer):
def validate_privacy_accepted(self, value):
if not value:
raise serializers.ValidationError("Необходимо принять условия политики конфиденциальности")
return value
def create(self, validated_data):
privacy_accepted = validated_data.pop('privacy_accepted')
phone_number = validated_data.pop('phone_number')
name = validated_data.pop('first_name')
name = validated_data.pop('name')
surname = validated_data.pop('surname')
try:
user = User.objects.create_user(
username=validated_data['name'],
username=validated_data['email'], # используем email как username
email=validated_data['email'],
password=validated_data['password'],
first_name = name,
first_name=name,
last_name=surname
)
UserProfile.objects.create(

View File

@@ -1,6 +1,171 @@
from rest_framework import serializers
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken
import traceback
from django.contrib.auth.models import User
from django.conf import settings
from django.db.utils import IntegrityError
from django.contrib.auth.hashers import make_password
from django.db import IntegrityError, transaction
from .serializers import ClientRegisterSerializer, UserResponseSerializer
from api.utils.cookiesSet import AuthBaseViewSet
from datetime import datetime
class RegisterViewSet(AuthBaseViewSet):
"""Регистрация клиента"""
@action(detail=False, methods=['post'], url_path="clients")
def register_client(self, request):
serializer = ClientRegisterSerializer(data=request.data)
if serializer.is_valid():
try:
with transaction.atomic():
user = serializer.save()
refresh = RefreshToken.for_user(user)
user_data = UserResponseSerializer(user).data
response = Response(
{
"access": str(refresh.access_token),
"refresh": str(refresh),
"user": user_data
},
status=status.HTTP_201_CREATED
)
# используем метод из базового класса вместо прямой установки куки
return self._set_auth_cookies(response, refresh)
except IntegrityError as e:
return Response(
{"error": "Пользователь с таким email уже существует"},
status=status.HTTP_400_BAD_REQUEST
)
except Exception as e:
return Response(
{"error": str(e)},
status=status.HTTP_400_BAD_REQUEST
)
# ошибка валидации
return Response(
{
"error": "Ошибка валидации",
"details": serializer.errors
},
status=status.HTTP_400_BAD_REQUEST
)
class LoginViewSet(AuthBaseViewSet):
"""Логин для клиента"""
@action(detail=False, methods=['post'], url_path="clients")
def login_client(self, request):
try:
email = request.data.get("email")
password = request.data.get("password")
if not email or not password:
return Response(
{"error": "Email и пароль обязательны"},
status=status.HTTP_400_BAD_REQUEST
)
try:
user = User.objects.get(email=email)
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
user_data["userType"] = "client"
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):
"""Логаут"""
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
class RefreshTokenView(APIView):
def post(self, request):
try:
refresh_token = request.data.get('refresh')
if not refresh_token:
return Response(
{'error': 'Refresh token is required'},
status=status.HTTP_400_BAD_REQUEST
)
try:
token = RefreshToken(refresh_token)
# Сохраняем user_type при обновлении токена
if 'user_type' in token:
token.access_token['user_type'] = token['user_type']
# Добавляем точное время истечения токена
expires_at = datetime.now() + settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME']
response_data = {
'access': str(token.access_token),
'refresh': str(token),
'expires_at': datetime.timestamp(expires_at)
}
return Response(response_data)
except Exception as e:
# Более подробное логирование ошибок
print(f"Token refresh error: {str(e)}")
print(traceback.format_exc())
return Response(
{'error': f'Invalid refresh token: {str(e)}'},
status=status.HTTP_400_BAD_REQUEST
)
except Exception as e:
return Response(
{'error': f'Token refresh failed: {str(e)}'},
status=status.HTTP_400_BAD_REQUEST
)