Recruitment_site/offer_backend/apps/accounts/views.py

147 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from rest_framework import generics, status
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from django.contrib.auth import get_user_model
from django.core.mail import send_mail
from django.conf import settings
from .models import VerificationCode
from .serializers import RegisterSerializer, UserSerializer, AdminUserSerializer, SendCodeSerializer, LoginSerializer
from .permissions import IsSuperAdmin
User = get_user_model()
class SendCodeView(APIView):
"""发送邮箱验证码"""
permission_classes = [AllowAny]
def post(self, request):
serializer = SendCodeSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
email = serializer.validated_data['email']
# 清除旧验证码
VerificationCode.objects.filter(email=email).delete()
# 生成新验证码
code = VerificationCode.generate_code()
vc = VerificationCode.objects.create(email=email, code=code)
# 发送邮件
try:
send_mail(
subject='【集团招聘平台】登入验证码',
message=f'您的验证码是:{code}\n\n验证码有效期为10分钟请勿泄露给他人。',
from_email=getattr(settings, 'DEFAULT_FROM_EMAIL', 'noreply@offer.com'),
recipient_list=[email],
fail_silently=False,
)
except Exception as e:
vc.delete()
return Response(
{'error': '邮件发送失败,请稍后重试'},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
return Response({'message': '验证码已发送到您的邮箱'})
class CustomTokenObtainPairView(TokenObtainPairView):
"""自定义登入视图,支持邮箱验证码和用户名密码两种方式"""
def post(self, request, *args, **kwargs):
# 判断是否是邮箱验证码登入(有 email 和 code还是用户名密码登入有 username 和 password
if 'email' in request.data and 'code' in request.data:
# 邮箱验证码登入
return self._login_with_code(request)
elif 'username' in request.data and 'password' in request.data:
# 用户名密码登入
return self._login_with_password(request)
else:
return Response(
{'error': '请提供正确的登入方式'},
status=status.HTTP_400_BAD_REQUEST
)
def _login_with_code(self, request):
"""邮箱验证码登入"""
serializer = LoginSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
vc = serializer.validated_data['vc']
# 标记验证码为已使用
vc.mark_as_verified()
# 生成 JWT token
from rest_framework_simplejwt.tokens import RefreshToken
refresh = RefreshToken.for_user(user)
return Response({
'refresh': str(refresh),
'access': str(refresh.access_token),
}, status=status.HTTP_200_OK)
def _login_with_password(self, request):
"""用户名密码登入"""
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
serializer = TokenObtainPairSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.validated_data, status=status.HTTP_200_OK)
class RegisterView(APIView):
"""邮箱验证码注册"""
permission_classes = [AllowAny]
def post(self, request):
serializer = RegisterSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
# 创建用户
user = serializer.save()
# 生成 JWT token
from rest_framework_simplejwt.tokens import RefreshToken
refresh = RefreshToken.for_user(user)
return Response({
'user': {
'id': user.id,
'username': user.username,
'email': user.email,
'role': user.role,
},
'refresh': str(refresh),
'access': str(refresh.access_token),
}, status=status.HTTP_201_CREATED)
class MeView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
return Response(UserSerializer(request.user).data)
def patch(self, request):
serializer = UserSerializer(request.user, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
class UserManageViewSet(generics.ListCreateAPIView):
"""超管:管理所有用户"""
serializer_class = AdminUserSerializer
permission_classes = [IsSuperAdmin]
queryset = User.objects.all()
class UserDetailView(generics.RetrieveUpdateDestroyAPIView):
serializer_class = AdminUserSerializer
permission_classes = [IsSuperAdmin]
queryset = User.objects.all()