views.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import base64
  2. import hashlib
  3. import hmac
  4. import logging
  5. from django import http
  6. from django.conf import settings
  7. from django.core.files.storage import default_storage
  8. from django.views import generic
  9. logger = logging.getLogger("s3file")
  10. class S3MockView(generic.View):
  11. def post(self, request):
  12. success_action_status = request.POST.get("success_action_status", 201)
  13. try:
  14. file = request.FILES["file"]
  15. key = request.POST["key"]
  16. date = request.POST["x-amz-date"]
  17. signature = request.POST["x-amz-signature"]
  18. policy = request.POST["policy"]
  19. except KeyError:
  20. logger.exception("bad request")
  21. return http.HttpResponseBadRequest()
  22. try:
  23. signature = base64.b64decode(signature.encode())
  24. policy = base64.b64decode(policy.encode())
  25. calc_sign = hmac.new(
  26. settings.SECRET_KEY.encode(), policy + date.encode(), "sha256"
  27. ).digest()
  28. except ValueError:
  29. logger.exception("bad request")
  30. return http.HttpResponseBadRequest()
  31. if not hmac.compare_digest(signature, calc_sign):
  32. logger.warning("bad signature")
  33. return http.HttpResponseForbidden()
  34. key = key.replace("${filename}", file.name)
  35. etag = hashlib.md5(file.read()).hexdigest() # nosec
  36. file.seek(0)
  37. key = default_storage.save(key, file)
  38. return http.HttpResponse(
  39. '<?xml version="1.0" encoding="UTF-8"?>'
  40. "<PostResponse>"
  41. f"<Location>{settings.MEDIA_URL}{key}</Location>"
  42. f"<Bucket>{getattr(settings, 'AWS_STORAGE_BUCKET_NAME')}</Bucket>"
  43. f"<Key>{key}</Key>"
  44. f'<ETag>"{etag}"</ETag>'
  45. "</PostResponse>",
  46. status=success_action_status,
  47. )