""" Views for user authentication and management. """ from rest_framework import generics, status from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated, AllowAny from rest_framework.response import Response from rest_framework_simplejwt.tokens import RefreshToken from django.contrib.auth import get_user_model from django.db import transaction from .models import User, UserProfile, APIKey from .serializers import ( UserRegistrationSerializer, UserLoginSerializer, UserSerializer, UserProfileSerializer, UserUpdateSerializer, PasswordChangeSerializer, APIKeySerializer, APIKeyCreateSerializer, SubscriptionUpdateSerializer ) User = get_user_model() class UserRegistrationView(generics.CreateAPIView): """User registration endpoint.""" queryset = User.objects.all() serializer_class = UserRegistrationSerializer permission_classes = [AllowAny] def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) with transaction.atomic(): user = serializer.save() # Create user profile UserProfile.objects.create(user=user) # Generate tokens refresh = RefreshToken.for_user(user) return Response({ 'message': 'User created successfully', 'user': UserSerializer(user).data, 'tokens': { 'refresh': str(refresh), 'access': str(refresh.access_token), } }, status=status.HTTP_201_CREATED) @api_view(['POST']) @permission_classes([AllowAny]) def login_view(request): """User login endpoint.""" serializer = UserLoginSerializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] refresh = RefreshToken.for_user(user) return Response({ 'message': 'Login successful', 'user': UserSerializer(user).data, 'tokens': { 'refresh': str(refresh), 'access': str(refresh.access_token), } }) @api_view(['POST']) @permission_classes([IsAuthenticated]) def logout_view(request): """User logout endpoint.""" try: refresh_token = request.data["refresh"] token = RefreshToken(refresh_token) token.blacklist() return Response({'message': 'Logout successful'}) except Exception as e: return Response({'error': 'Invalid token'}, status=status.HTTP_400_BAD_REQUEST) class UserProfileView(generics.RetrieveUpdateAPIView): """User profile management.""" serializer_class = UserSerializer permission_classes = [IsAuthenticated] def get_object(self): return self.request.user class UserUpdateView(generics.UpdateAPIView): """Update user information.""" serializer_class = UserUpdateSerializer permission_classes = [IsAuthenticated] def get_object(self): return self.request.user @api_view(['POST']) @permission_classes([IsAuthenticated]) def change_password_view(request): """Change user password.""" serializer = PasswordChangeSerializer(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) user = request.user user.set_password(serializer.validated_data['new_password']) user.save() return Response({'message': 'Password changed successfully'}) class UserProfileDetailView(generics.RetrieveUpdateAPIView): """User profile detail management.""" serializer_class = UserProfileSerializer permission_classes = [IsAuthenticated] def get_object(self): profile, created = UserProfile.objects.get_or_create(user=self.request.user) return profile class APIKeyListView(generics.ListCreateAPIView): """List and create API keys.""" permission_classes = [IsAuthenticated] def get_serializer_class(self): if self.request.method == 'POST': return APIKeyCreateSerializer return APIKeySerializer def get_queryset(self): return APIKey.objects.filter(user=self.request.user, is_active=True) def perform_create(self, serializer): serializer.save(user=self.request.user) class APIKeyDetailView(generics.RetrieveUpdateDestroyAPIView): """API key detail management.""" serializer_class = APIKeySerializer permission_classes = [IsAuthenticated] def get_queryset(self): return APIKey.objects.filter(user=self.request.user) def perform_destroy(self, instance): instance.is_active = False instance.save() @api_view(['POST']) @permission_classes([IsAuthenticated]) def regenerate_api_key_view(request): """Regenerate user's main API key.""" user = request.user if not user.is_api_enabled: return Response( {'error': 'API access is not enabled for this user'}, status=status.HTTP_400_BAD_REQUEST ) user.api_key = user.generate_api_key() user.save() return Response({ 'message': 'API key regenerated successfully', 'api_key': user.api_key }) @api_view(['POST']) @permission_classes([IsAuthenticated]) def toggle_api_access_view(request): """Toggle API access for user.""" user = request.user if not user.api_key: user.api_key = user.generate_api_key() user.is_api_enabled = not user.is_api_enabled user.save() return Response({ 'message': f'API access {"enabled" if user.is_api_enabled else "disabled"}', 'is_api_enabled': user.is_api_enabled, 'api_key': user.api_key if user.is_api_enabled else None }) @api_view(['POST']) @permission_classes([IsAuthenticated]) def update_subscription_view(request): """Update user subscription (admin only).""" if not request.user.is_staff: return Response( {'error': 'Permission denied'}, status=status.HTTP_403_FORBIDDEN ) serializer = SubscriptionUpdateSerializer(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) user_id = request.data.get('user_id') if not user_id: return Response( {'error': 'user_id is required'}, status=status.HTTP_400_BAD_REQUEST ) try: user = User.objects.get(id=user_id) except User.DoesNotExist: return Response( {'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND ) user.subscription_type = serializer.validated_data['subscription_type'] user.save() return Response({ 'message': 'Subscription updated successfully', 'user': UserSerializer(user).data }) class UserListView(generics.ListAPIView): """List all users (admin only).""" serializer_class = UserSerializer permission_classes = [IsAuthenticated] def get_queryset(self): if not self.request.user.is_staff: return User.objects.none() return User.objects.all().order_by('-date_joined') @api_view(['GET']) @permission_classes([IsAuthenticated]) def get_current_user(request): """Get current authenticated user.""" serializer = UserSerializer(request.user) return Response(serializer.data)