from rest_framework import status from rest_framework.decorators import api_view, permission_classes, throttle_classes from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.response import Response from rest_framework.throttling import ScopedRateThrottle from rest_framework_simplejwt.tokens import RefreshToken from django.contrib.auth import authenticate, get_user_model from django.utils import timezone from django.db.models import Sum from .serializers import UserSerializer User = get_user_model() class LoginRateThrottle(ScopedRateThrottle): scope = 'login' @api_view(['POST']) @permission_classes([AllowAny]) def register_view(request): """POST /api/v1/auth/register — disabled, all accounts created by admins.""" return Response( {'error': 'registration_disabled', 'message': '公开注册已关闭,请联系管理员'}, status=status.HTTP_403_FORBIDDEN, ) @api_view(['POST']) @permission_classes([AllowAny]) @throttle_classes([LoginRateThrottle]) def login_view(request): """POST /api/v1/auth/login""" username = request.data.get('username', '').strip() password = request.data.get('password', '') # Try authenticate with username first, then email user = authenticate(username=username, password=password) if user is None: # Try email login try: user_by_email = User.objects.get(email=username) user = authenticate(username=user_by_email.username, password=password) except User.DoesNotExist: pass if user is None: return Response( {'error': 'invalid_credentials', 'message': '用户名或密码错误'}, status=status.HTTP_401_UNAUTHORIZED ) refresh = RefreshToken.for_user(user) return Response({ 'user': UserSerializer(user).data, 'tokens': { 'access': str(refresh.access_token), 'refresh': str(refresh), } }) @api_view(['GET']) @permission_classes([IsAuthenticated]) def me_view(request): """GET /api/v1/auth/me — returns role, team info, and quota.""" user = request.user today = timezone.now().date() first_of_month = today.replace(day=1) daily_seconds_used = user.generation_records.filter( created_at__date=today ).aggregate(total=Sum('seconds_consumed'))['total'] or 0 monthly_seconds_used = user.generation_records.filter( created_at__date__gte=first_of_month ).aggregate(total=Sum('seconds_consumed'))['total'] or 0 data = UserSerializer(user).data data['quota'] = { 'daily_seconds_limit': user.daily_seconds_limit, 'daily_seconds_used': daily_seconds_used, 'monthly_seconds_limit': user.monthly_seconds_limit, 'monthly_seconds_used': monthly_seconds_used, } # Team info team = user.team if team: # Team monthly consumption from apps.generation.models import GenerationRecord team_monthly_used = GenerationRecord.objects.filter( user__team=team, created_at__date__gte=first_of_month, ).aggregate(total=Sum('seconds_consumed'))['total'] or 0 data['team'] = { 'id': team.id, 'name': team.name, 'total_seconds_pool': team.total_seconds_pool, 'total_seconds_used': team.total_seconds_used, 'remaining_seconds': team.remaining_seconds, 'monthly_seconds_limit': team.monthly_seconds_limit, 'monthly_seconds_used': team_monthly_used, 'is_active': team.is_active, } data['team_disabled'] = not team.is_active else: data['team'] = None data['team_disabled'] = False return Response(data)