loko/loko/bim/views.py

92 lines
3.4 KiB
Python

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,
})