""" ============================================== VIEWS COMPLETS - EDUCONNECT AFRICA API ============================================== """ # ============================================ # apps/users/views.py # ============================================ from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, AllowAny from rest_framework_simplejwt.tokens import RefreshToken from rest_framework.parsers import MultiPartParser, FormParser from django.db import transaction from django.core.files.storage import default_storage from django.core.files.base import ContentFile import os import uuid from apps.users.models import User, UserAvatar from apps.users.serializers import ( UserSerializer, UserRegistrationSerializer, UserLoginSerializer, UserProfileUpdateSerializer ) class AuthViewSet(viewsets.GenericViewSet): """Gestion de l'authentification""" permission_classes = [AllowAny] @action(detail=False, methods=['post']) def register(self, request): """POST /api/auth/register/""" serializer = UserRegistrationSerializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.save() # Générer tokens JWT refresh = RefreshToken.for_user(user) return Response({ 'user': UserSerializer(user).data, 'tokens': { 'refresh': str(refresh), 'access': str(refresh.access_token), } }, status=status.HTTP_201_CREATED) @action(detail=False, methods=['post']) def login(self, request): """POST /api/auth/login/""" serializer = UserLoginSerializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] # Générer tokens JWT refresh = RefreshToken.for_user(user) # Mettre à jour last_login from django.utils import timezone user.last_login = timezone.now() user.last_login_ip = request.META.get('REMOTE_ADDR') user.save(update_fields=['last_login', 'last_login_ip']) return Response({ 'user': UserSerializer(user).data, 'tokens': { 'refresh': str(refresh), 'access': str(refresh.access_token), } }) @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated]) def me(self, request): """GET /api/auth/me/""" serializer = UserSerializer(request.user) return Response(serializer.data) @action(detail=False, methods=['patch'], permission_classes=[IsAuthenticated], url_path='profile') def update_profile(self, request): """PATCH /api/auth/profile/""" serializer = UserProfileUpdateSerializer( request.user, data=request.data, partial=True ) if not serializer.is_valid(): import logging logger = logging.getLogger('django') logger.warning(f"Bad Request: {request.path}") logger.warning(f"Validation errors: {serializer.errors}") serializer.is_valid(raise_exception=True) serializer.save() return Response(UserSerializer(request.user).data) @action( detail=False, methods=['post'], permission_classes=[IsAuthenticated], parser_classes=[MultiPartParser, FormParser], url_path='upload-avatar' ) def upload_avatar(self, request): """POST /api/auth/upload-avatar/ - Upload avatar image""" if 'avatar' not in request.FILES: return Response( {'error': 'No avatar file provided'}, status=status.HTTP_400_BAD_REQUEST ) avatar_file = request.FILES['avatar'] # Validate file type allowed_types = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'] if avatar_file.content_type not in allowed_types: return Response( {'error': 'Invalid file type. Only JPEG, PNG, GIF, and WebP are allowed.'}, status=status.HTTP_400_BAD_REQUEST ) # Validate file size (max 5MB) if avatar_file.size > 5 * 1024 * 1024: return Response( {'error': 'File too large. Maximum size is 5MB.'}, status=status.HTTP_400_BAD_REQUEST ) try: # Generate unique filename ext = os.path.splitext(avatar_file.name)[1] filename = f"avatars/{request.user.id}/{uuid.uuid4()}{ext}" # Save file path = default_storage.save(filename, ContentFile(avatar_file.read())) avatar_url = default_storage.url(path) # Get user profile (handle multiple profiles case) from apps.users.models import UserProfile profile = UserProfile.objects.filter(user=request.user, is_current=True).first() # If no current profile exists, create one if not profile: profile = UserProfile.objects.create( user=request.user, name=request.user.name ) # Deactivate old avatars profile.avatars.filter(is_current=True).update(is_current=False) # Create new avatar record UserAvatar.objects.create( profile=profile, avatar_url=avatar_url ) return Response({ 'avatar_url': avatar_url, 'message': 'Avatar uploaded successfully' }) except Exception as e: import logging logger = logging.getLogger('django') logger.error(f"Avatar upload error: {str(e)}") return Response( {'error': 'Failed to upload avatar'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR )