from rest_framework import generics, status, permissions from rest_framework.decorators import api_view, permission_classes from rest_framework.response import Response from rest_framework.views import APIView from django.shortcuts import get_object_or_404 from django.db.models import Q from django.contrib.auth import get_user_model from .models import FolderStructure, FolderPermission, FolderBookmark, FolderActivity from .serializers import ( FolderStructureSerializer, FolderPermissionSerializer, FolderBookmarkSerializer, FolderActivitySerializer, FolderCreateSerializer, FolderShareSerializer, FolderMoveSerializer ) User = get_user_model() class FolderListCreateView(generics.ListCreateAPIView): """List and create folders.""" permission_classes = [permissions.IsAuthenticated] def get_serializer_class(self): if self.request.method == 'POST': return FolderCreateSerializer return FolderStructureSerializer def get_queryset(self): user = self.request.user return FolderStructure.objects.filter( Q(user=user) | Q(permissions__user=user) ).distinct().order_by('sort_order', 'name') def perform_create(self, serializer): folder = serializer.save(user=self.request.user) # Log activity FolderActivity.objects.create( folder=folder, user=self.request.user, activity_type='created', description=f"Created folder '{folder.name}'" ) class FolderDetailView(generics.RetrieveUpdateDestroyAPIView): """Retrieve, update, or delete folder.""" serializer_class = FolderStructureSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): user = self.request.user return FolderStructure.objects.filter( Q(user=user) | Q(permissions__user=user) ).distinct() def perform_update(self, serializer): folder = self.get_object() old_name = folder.name folder = serializer.save() # Log activity if old_name != folder.name: FolderActivity.objects.create( folder=folder, user=self.request.user, activity_type='renamed', description=f"Renamed folder from '{old_name}' to '{folder.name}'" ) else: FolderActivity.objects.create( folder=folder, user=self.request.user, activity_type='updated', description=f"Updated folder '{folder.name}'" ) def perform_destroy(self, instance): # Log activity FolderActivity.objects.create( folder=instance, user=self.request.user, activity_type='deleted', description=f"Deleted folder '{instance.name}'" ) instance.delete() class FolderTreeView(generics.ListAPIView): """Get folder tree structure.""" serializer_class = FolderStructureSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): user = self.request.user return FolderStructure.objects.filter( Q(user=user) | Q(permissions__user=user), parent__isnull=True ).distinct().order_by('sort_order', 'name') class FolderPermissionListCreateView(generics.ListCreateAPIView): """List and create folder permissions.""" serializer_class = FolderPermissionSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): folder_id = self.kwargs.get('folder_id') folder = get_object_or_404(FolderStructure, id=folder_id) # Check if user owns the folder or has admin permission if folder.user != self.request.user: permission = FolderPermission.objects.filter( folder=folder, user=self.request.user, permission='admin' ).exists() if not permission: return FolderPermission.objects.none() return FolderPermission.objects.filter(folder=folder) def perform_create(self, serializer): folder_id = self.kwargs.get('folder_id') folder = get_object_or_404(FolderStructure, id=folder_id) # Check if user owns the folder or has admin permission if folder.user != self.request.user: permission = FolderPermission.objects.filter( folder=folder, user=self.request.user, permission='admin' ).exists() if not permission: raise PermissionError("You don't have permission to share this folder.") # Get user to share with user_email = serializer.validated_data['user_email'] user_to_share = get_object_or_404(User, email=user_email) # Create permission permission = FolderPermission.objects.create( folder=folder, user=user_to_share, permission=serializer.validated_data['permission'], granted_by=self.request.user ) # Log activity FolderActivity.objects.create( folder=folder, user=self.request.user, activity_type='shared', description=f"Shared folder '{folder.name}' with {user_email} ({permission.permission} permission)" ) class FolderPermissionDetailView(generics.RetrieveUpdateDestroyAPIView): """Retrieve, update, or delete folder permission.""" serializer_class = FolderPermissionSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): folder_id = self.kwargs.get('folder_id') folder = get_object_or_404(FolderStructure, id=folder_id) # Check if user owns the folder or has admin permission if folder.user != self.request.user: permission = FolderPermission.objects.filter( folder=folder, user=self.request.user, permission='admin' ).exists() if not permission: return FolderPermission.objects.none() return FolderPermission.objects.filter(folder=folder) class FolderBookmarkListCreateView(generics.ListCreateAPIView): """List and create folder bookmarks.""" serializer_class = FolderBookmarkSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return FolderBookmark.objects.filter(user=self.request.user) def perform_create(self, serializer): folder_id = self.kwargs.get('folder_id') folder = get_object_or_404(FolderStructure, id=folder_id) # Check if user has access to the folder if folder.user != self.request.user: permission = FolderPermission.objects.filter( folder=folder, user=self.request.user ).exists() if not permission: raise PermissionError("You don't have access to this folder.") serializer.save(user=self.request.user, folder=folder) class FolderBookmarkDetailView(generics.RetrieveDestroyAPIView): """Retrieve or delete folder bookmark.""" serializer_class = FolderBookmarkSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return FolderBookmark.objects.filter(user=self.request.user) class FolderActivityView(generics.ListAPIView): """List folder activities.""" serializer_class = FolderActivitySerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): folder_id = self.kwargs.get('folder_id') folder = get_object_or_404(FolderStructure, id=folder_id) # Check if user has access to the folder if folder.user != self.request.user: permission = FolderPermission.objects.filter( folder=folder, user=self.request.user ).exists() if not permission: return FolderActivity.objects.none() return FolderActivity.objects.filter(folder=folder) @api_view(['POST']) @permission_classes([permissions.IsAuthenticated]) def share_folder(request, folder_id): """Share a folder with another user.""" folder = get_object_or_404(FolderStructure, id=folder_id) # Check if user owns the folder if folder.user != request.user: return Response( {'error': 'You can only share folders you own'}, status=status.HTTP_403_FORBIDDEN ) serializer = FolderShareSerializer(data=request.data, context={'request': request}) if serializer.is_valid(): user_email = serializer.validated_data['user_email'] permission = serializer.validated_data['permission'] try: user_to_share = User.objects.get(email=user_email) except User.DoesNotExist: return Response( {'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND ) # Create or update permission permission_obj, created = FolderPermission.objects.get_or_create( folder=folder, user=user_to_share, defaults={ 'permission': permission, 'granted_by': request.user } ) if not created: permission_obj.permission = permission permission_obj.granted_by = request.user permission_obj.save() # Make folder shared folder.is_shared = True folder.save() # Log activity FolderActivity.objects.create( folder=folder, user=request.user, activity_type='shared', description=f"Shared folder '{folder.name}' with {user_email} ({permission} permission)" ) return Response({ 'message': f'Folder shared with {user_email}', 'permission': FolderPermissionSerializer(permission_obj).data }) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(['POST']) @permission_classes([permissions.IsAuthenticated]) def move_folder(request, folder_id): """Move a folder to a new location.""" folder = get_object_or_404(FolderStructure, id=folder_id) # Check if user owns the folder if folder.user != request.user: return Response( {'error': 'You can only move folders you own'}, status=status.HTTP_403_FORBIDDEN ) serializer = FolderMoveSerializer(data=request.data, context={'request': request}) if serializer.is_valid(): new_parent = serializer.validated_data.get('new_parent') new_sort_order = serializer.validated_data.get('new_sort_order') old_parent = folder.parent old_sort_order = folder.sort_order # Update folder folder.parent = new_parent if new_sort_order is not None: folder.sort_order = new_sort_order folder.save() # Log activity FolderActivity.objects.create( folder=folder, user=request.user, activity_type='moved', description=f"Moved folder '{folder.name}' from {old_parent.name if old_parent else 'root'} to {new_parent.name if new_parent else 'root'}" ) return Response({ 'message': 'Folder moved successfully', 'folder': FolderStructureSerializer(folder).data }) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(['GET']) @permission_classes([permissions.IsAuthenticated]) def folder_stats(request): """Get folder statistics.""" user = request.user stats = { 'total_folders': FolderStructure.objects.filter(user=user).count(), 'shared_folders': FolderStructure.objects.filter(user=user, is_shared=True).count(), 'bookmarked_folders': FolderBookmark.objects.filter(user=user).count(), 'recent_activities': FolderActivity.objects.filter( Q(folder__user=user) | Q(folder__permissions__user=user) ).distinct().count(), } return Response(stats)