attachment.py 2.3 KB

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