attachment.py 2.2 KB

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