120 lines
3.7 KiB
Python
120 lines
3.7 KiB
Python
"""
|
|
Topic-based file sharing views.
|
|
|
|
Each topic is accessible via a subdomain (e.g., cofi.rfiles.online).
|
|
Anyone can view files and upload new ones - no password required.
|
|
"""
|
|
|
|
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.http import JsonResponse, Http404
|
|
from django.views import View
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.utils.decorators import method_decorator
|
|
|
|
from files.models import SharedSpace, MediaFile, PublicShare
|
|
|
|
|
|
def get_topic_or_404(request):
|
|
"""Get the topic (shared space) from the request's subdomain slug."""
|
|
slug = getattr(request, 'shared_space_slug', None)
|
|
if not slug:
|
|
raise Http404("Topic not found")
|
|
return get_object_or_404(SharedSpace, slug=slug, is_active=True)
|
|
|
|
|
|
class SharedSpaceLoginView(View):
|
|
"""Redirect login to home - no login needed for topics."""
|
|
|
|
def get(self, request):
|
|
return redirect('shared_space_home')
|
|
|
|
def post(self, request):
|
|
return redirect('shared_space_home')
|
|
|
|
|
|
class SharedSpaceLogoutView(View):
|
|
"""Redirect to home - no logout needed."""
|
|
|
|
def get(self, request):
|
|
return redirect('shared_space_home')
|
|
|
|
|
|
class SharedSpaceHomeView(View):
|
|
"""Main upload page for topic - upload zone + files."""
|
|
|
|
def get(self, request):
|
|
space = get_topic_or_404(request)
|
|
recent_files = space.files.all().order_by('-created_at')[:20]
|
|
|
|
return render(request, 'portal/shared_space/home.html', {
|
|
'space': space,
|
|
'recent_files': recent_files,
|
|
})
|
|
|
|
|
|
@method_decorator(csrf_exempt, name='dispatch')
|
|
class SharedSpaceUploadAPIView(View):
|
|
"""Handle file uploads via AJAX for topic."""
|
|
|
|
def post(self, request):
|
|
space = get_topic_or_404(request)
|
|
|
|
if not request.FILES.get('file'):
|
|
return JsonResponse({'error': 'No file provided'}, status=400)
|
|
|
|
uploaded_file = request.FILES['file']
|
|
|
|
if space.max_file_size_mb > 0:
|
|
max_size_bytes = space.max_file_size_mb * 1024 * 1024
|
|
if uploaded_file.size > max_size_bytes:
|
|
return JsonResponse({
|
|
'error': f'File too large. Maximum size is {space.max_file_size_mb}MB'
|
|
}, status=400)
|
|
|
|
title = request.POST.get('title', '') or uploaded_file.name
|
|
description = request.POST.get('description', '')
|
|
|
|
media_file = MediaFile.objects.create(
|
|
file=uploaded_file,
|
|
original_filename=uploaded_file.name,
|
|
title=title,
|
|
description=description,
|
|
mime_type=uploaded_file.content_type or 'application/octet-stream',
|
|
uploaded_by=request.user if request.user.is_authenticated else None,
|
|
shared_space=space,
|
|
)
|
|
|
|
share = PublicShare.objects.create(
|
|
media_file=media_file,
|
|
created_by=request.user if request.user.is_authenticated else None,
|
|
note=f'Uploaded to topic: {space.slug}',
|
|
)
|
|
|
|
return JsonResponse({
|
|
'success': True,
|
|
'file': {
|
|
'id': str(media_file.id),
|
|
'title': media_file.title,
|
|
'filename': media_file.original_filename,
|
|
'size': media_file.file_size,
|
|
'mime_type': media_file.mime_type,
|
|
},
|
|
'share': {
|
|
'token': share.token,
|
|
'url': share.get_public_url(),
|
|
}
|
|
})
|
|
|
|
|
|
class SharedSpaceFileListView(View):
|
|
"""List all files in the topic."""
|
|
|
|
def get(self, request):
|
|
space = get_topic_or_404(request)
|
|
files = space.files.all().order_by('-created_at')
|
|
|
|
return render(request, 'portal/shared_space/files.html', {
|
|
'space': space,
|
|
'files': files,
|
|
})
|