attachment.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. from django.core.exceptions import PermissionDenied
  2. from django.http import Http404
  3. from django.shortcuts import get_object_or_404, redirect
  4. from ...conf import settings
  5. from ..models import Attachment, AttachmentType
  6. ATTACHMENT_404_URL = "".join((settings.STATIC_URL, settings.MISAGO_404_IMAGE))
  7. ATTACHMENT_403_URL = "".join((settings.STATIC_URL, settings.MISAGO_403_IMAGE))
  8. def attachment_server(request, pk, secret, thumbnail=False):
  9. try:
  10. url = serve_file(request, pk, secret, thumbnail)
  11. return redirect(url)
  12. except Http404:
  13. return redirect(ATTACHMENT_404_URL)
  14. except PermissionDenied:
  15. return redirect(ATTACHMENT_403_URL)
  16. def serve_file(request, pk, secret, thumbnail):
  17. queryset = Attachment.objects.select_related("filetype")
  18. attachment = get_object_or_404(queryset, pk=pk, secret=secret)
  19. if not attachment.post_id and request.GET.get("shva") != "1":
  20. # if attachment is orphaned, don't run acl test unless explictly told so
  21. # this saves user suprise of deleted attachment still showing in posts/quotes
  22. raise Http404()
  23. if not request.user.is_staff:
  24. allow_file_download(request, attachment)
  25. if attachment.is_image:
  26. if thumbnail:
  27. return attachment.thumbnail.url
  28. return attachment.image.url
  29. if thumbnail:
  30. raise Http404()
  31. return attachment.file.url
  32. def allow_file_download(request, attachment):
  33. is_authenticated = request.user.is_authenticated
  34. if not is_authenticated or request.user.id != attachment.uploader_id:
  35. if not attachment.post_id:
  36. raise Http404()
  37. if not request.user_acl["can_download_other_users_attachments"]:
  38. raise PermissionDenied()
  39. allowed_roles = set(r.pk for r in attachment.filetype.limit_downloads_to.all())
  40. if allowed_roles:
  41. user_roles = set(r.pk for r in request.user.get_roles())
  42. if not user_roles & allowed_roles:
  43. raise PermissionDenied()
  44. if attachment.filetype.status == AttachmentType.DISABLED:
  45. raise PermissionDenied()