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, CodeLoginSerializer, PasswordLoginSerializer, ResetPasswordSerializer, ConfirmResetPasswordSerializer 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 RequestResetPasswordView(APIView): """请求密码重置(发送验证码)""" permission_classes = [AllowAny] def post(self, request): serializer = ResetPasswordSerializer(data=request.data) serializer.is_valid(raise_exception=True) email = serializer.validated_data['email'] # 使用 SendCodeView 的逻辑发送验证码 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 ConfirmResetPasswordView(APIView): """确认密码重置""" permission_classes = [AllowAny] def post(self, request): serializer = ConfirmResetPasswordSerializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] vc = serializer.validated_data['vc'] new_password = serializer.validated_data['new_password'] # 设置新密码 user.set_password(new_password) user.save() # 标记验证码为已使用 vc.mark_as_verified() return Response({'message': '密码重置成功,请使用新密码登入'}) class CustomTokenObtainPairView(TokenObtainPairView): """自定义登入视图,支持三种方式:邮箱验证码、邮箱密码、用户名密码""" def post(self, request, *args, **kwargs): # 判断登入方式 has_code = 'code' in request.data has_email = 'email' in request.data has_username = 'username' in request.data has_password = 'password' in request.data if has_email and has_code: # 邮箱验证码登入 return self._login_with_code(request) elif (has_email or has_username) and has_password: # 邮箱或用户名 + 密码登入 return self._login_with_password(request) else: return Response( {'error': '请提供正确的登入方式'}, status=status.HTTP_400_BAD_REQUEST ) def _login_with_code(self, request): """邮箱验证码登入""" serializer = CodeLoginSerializer(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): """邮箱或用户名 + 密码登入""" serializer = PasswordLoginSerializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] # 生成 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) 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()