import os from django.conf import settings from django.core.exceptions import PermissionDenied from django.http import FileResponse, JsonResponse, Http404 from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from documents.models import ManagedDocument from documents.permissions import user_has_document_permission def _get_document_by_code(doc_code): """Utility to fetch ManagedDocument by UUID string/object or integer PK.""" try: return ManagedDocument.objects.get(uuid=doc_code) except (ManagedDocument.DoesNotExist, ValueError): # Fallback to PK lookup if integer passed if str(doc_code).isdigit(): return get_object_or_404(ManagedDocument, pk=int(doc_code)) raise Http404("Document non trouvé") @login_required def ifc_viewer_view(request, doc_code): """Renders the full-screen 3D IFC Viewer page for a given document code.""" document = _get_document_by_code(doc_code) if not user_has_document_permission(request.user, document, required_permission=ManagedDocument.PERMISSION_VIEW): raise PermissionDenied("Vous n'avez pas la permission de visualiser ce document.") version = document.latest_version if not version or not version.file: raise Http404("Aucun fichier disponible pour ce document.") filename = version.filename ext = os.path.splitext(filename)[1].lower() context = { "document": document, "version": version, "filename": filename, "ext": ext, "doc_code": document.uuid, } return render(request, "bim/viewer.html", context) @login_required def ifc_file_download_view(request, doc_code): """Streams the IFC file for consumption by the WebGL 3D viewer.""" document = _get_document_by_code(doc_code) if not user_has_document_permission(request.user, document, required_permission=ManagedDocument.PERMISSION_VIEW): raise PermissionDenied("Accès refusé.") version = document.latest_version if not version or not version.file: raise Http404("Fichier non trouvé.") response = FileResponse( version.file.open("rb"), content_type="application/octet-stream", filename=version.filename ) # Enable CORS headers if viewer runs under different subdomains / frames response["Access-Control-Allow-Origin"] = "*" response["Accept-Ranges"] = "bytes" return response @login_required def ifc_document_info_api(request, doc_code): """API endpoint providing document metadata for the BIM viewer UI.""" document = _get_document_by_code(doc_code) if not user_has_document_permission(request.user, document, required_permission=ManagedDocument.PERMISSION_VIEW): return JsonResponse({"error": "Accès refusé"}, status=403) version = document.latest_version file_size = version.file.size if version and version.file else 0 return JsonResponse({ "uuid": str(document.uuid), "id": document.id, "title": document.title, "description": document.description or "", "filename": version.filename if version else "", "version_number": version.version_number if version else 1, "file_size": file_size, "created_at": document.created_at.isoformat() if document.created_at else None, "updated_at": document.updated_at.isoformat() if document.updated_at else None, })