def test_copy_succeeds(self): from drf_to_s3 import s3 s3.copy( src_bucket=self.bucket_name, src_key=self.existing_key, dst_bucket=self.bucket, dst_key=self.nonexisting_key, src_etag=self.existing_key_etag, validate_src_etag=True )
def test_copy_fails_on_nonexistent_key(self): from drf_to_s3 import s3 another_nonexisting_key = str(uuid.uuid4()) + '.txt' with self.assertRaises(s3.ObjectNotFoundException): s3.copy( src_bucket=self.bucket_name, src_key=another_nonexisting_key, dst_bucket=self.bucket_name, dst_key=self.nonexisting_key, src_etag=self.existing_key_etag, validate_src_etag=True )
def copy_upload_to_storage(self, request, bucket, key, uuid, name, etag): ''' ''' import uuid as _uuid from drf_to_s3 import s3 target s3.copy( src_bucket=bucket, src_key=key, etag=etag, dst_bucket=self.bucket, dst_key=self.nonexisting_key )
def test_copy_succeeds_without_etag_validation_after_subsequent_update(self): from boto.s3.key import Key from drf_to_s3 import s3 k = Key(self.bucket) k.key = self.existing_key k.set_contents_from_string('Another test') s3.copy( src_bucket=self.bucket_name, src_key=self.existing_key, dst_bucket=self.bucket_name, dst_key=self.nonexisting_key )
def test_copy_fails_with_mismatched_etag_after_subsequent_update(self): from boto.s3.key import Key from drf_to_s3 import s3 k = Key(self.bucket) k.key = self.existing_key k.set_contents_from_string('Another test') with self.assertRaises(s3.ObjectNotFoundException): s3.copy( src_bucket=self.bucket_name, src_key=self.existing_key, dst_bucket=self.bucket_name, dst_key=self.nonexisting_key, src_etag=self.existing_key_etag, validate_src_etag=True )
def handle_upload(self, request, serializer, obj): ''' Subclasses should override, to provide handling for the successful upload. Subclasses may invoke invoke copy_upload_to_storage() to use the default logic, or use their own. Return a response with status=status.HTTP_200_OK. Return a specific error message in the `error` key. Under IE9 and IE8, if you return a non-200 status, only a generic error message can be displayed. To show a detailed error message, return a response with 200 status and an `error` key set. http://blog.fineuploader.com/2013/08/16/fine-uploader-s3-upload-directly-to-amazon-s3-from-your-browser/#success-endpoint make_error_response will do this with compatibility_for_iframe=True. Any other content you provide in the response is passed to the `complete` handler on the client. http://docs.fineuploader.com/api/events.html#complete request: The Django request bucket: S3 bucket key: Key name of the associated file in S3 uuid: UUID of the file name: Name of the file etag: The S3 etag of the S3 key Depending what you do with the uploaded file, you may need to validate that the request originated by this user, to prevent a malicious user from using this callback to hijack someone else's upload. Note: To avoid the need to configure the client to produce the prefixed upload URL, I'd rather prevent highjacking (due to vulnerable uuid generation) by having the client send the etag (which S3 provides to the client after a successful upload) in the completion handler. ''' import os, uuid from rest_framework import status from rest_framework.response import Response from drf_to_s3 import s3 bucket = obj['bucket'] key = obj['key'] name = obj['name'] basename, ext = os.path.splitext(name) new_key = str(uuid.uuid4()) + ext try: s3.copy( src_bucket=bucket, src_key=key, dst_bucket=self.get_aws_storage_bucket(), dst_key=new_key ) except s3.ObjectNotFoundException as e: return self.make_error_response( request=request, exception=e, compatibility_for_iframe=True ) return Response(status=status.HTTP_200_OK)