def test_upload_validator_using_wrong_extension(rf: RequestFactory): widget = AjaxUploadWidget( ajax_target_path="/ajax", upload_validators=[ ExtensionValidator(allowed_extensions=(".allowed-extension",)) ], ) widget.timeout = timedelta(seconds=1) content = load_test_data() upload_id = generate_new_upload_id( test_upload_validator_using_wrong_extension, content ) request = create_upload_file_request( rf, content=b"should error", filename="test.wrong_extension" ) response = widget.handle_ajax(request) assert response.status_code == 403 request = create_upload_file_request( rf, content=b"should error", filename="test.allowed-extension" ) response = widget.handle_ajax(request) assert response.status_code == 200
def test_inconsistent_chunks_rfc7233(rf: RequestFactory): widget = AjaxUploadWidget(ajax_target_path="/ajax") widget.timeout = timedelta(seconds=1) content = load_test_data() # Overlapping chunks upload_id = generate_new_upload_id( test_inconsistent_chunks_rfc7233, content ) part_1 = create_partial_upload_file_request(rf, upload_id, content, 0, 10) part_2 = create_partial_upload_file_request(rf, upload_id, content, 5, 15) widget.handle_ajax(part_1) assert isinstance(widget.handle_ajax(part_2), HttpResponseBadRequest) # Inconsistent filenames upload_id += "x" part_1 = create_partial_upload_file_request( rf, upload_id, content, 0, 10, filename="a" ) part_2 = create_partial_upload_file_request( rf, upload_id, content, 10, 20, filename="b" ) widget.handle_ajax(part_1) assert isinstance(widget.handle_ajax(part_2), HttpResponseBadRequest) # Inconsistent total size upload_id += "x" part_1 = create_partial_upload_file_request( rf, upload_id, content[:20], 0, 10 ) part_2 = create_partial_upload_file_request( rf, upload_id, content[:20], 10, 20 ) part_1.META["HTTP_CONTENT_RANGE"] = f"bytes 0-9/20" part_2.META["HTTP_CONTENT_RANGE"] = f"bytes 10-19/30" widget.handle_ajax(part_1) assert isinstance(widget.handle_ajax(part_2), HttpResponseBadRequest)
def test_wrong_upload_headers_rfc7233(rf: RequestFactory): widget = AjaxUploadWidget(ajax_target_path="/ajax") widget.timeout = timedelta(seconds=1) content = load_test_data() upload_id = generate_new_upload_id( test_wrong_upload_headers_rfc7233, content ) post_request = create_partial_upload_file_request( rf, upload_id, content, 0, 10 ) assert isinstance(widget.handle_ajax(post_request), JsonResponse) post_request = create_partial_upload_file_request( rf, upload_id, content, 0, 10 ) post_request.META["X-Upload-ID"] = None post_request = force_post_update(post_request, "X-Upload-ID", None) assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request( rf, upload_id, content, 0, 10 ) post_request.META[ "HTTP_CONTENT_RANGE" ] = "corrupted data: 54343-3223/21323" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request( rf, upload_id, content, 0, 10 ) post_request.META["HTTP_CONTENT_RANGE"] = "bytes 54343-3223/21323" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request( rf, upload_id, content, 0, 10 ) post_request.META["HTTP_CONTENT_RANGE"] = "bytes 54343-3223/*" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request( rf, upload_id, content, 0, 10 ) post_request.META["HTTP_CONTENT_RANGE"] = "bytes 1000-3000/2000" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request( rf, upload_id, content, 0, 10 ) post_request.META["HTTP_CONTENT_RANGE"] = "bytes 1000-2000/*" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request( rf, upload_id, content, 0, 10 ) post_request.META["X-Upload-ID"] = "a" * 1000 post_request = force_post_update(post_request, "X-Upload-ID", "a" * 1000) assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest)
def test_rfc7233_implementation_api(client): content = load_test_data() upload_id = generate_new_upload_id( test_rfc7233_implementation_api, content ) url = reverse("api:staged-file-list") _, token = AuthToken.objects.create(user=UserFactory()) part_1_response = create_partial_upload_file_request( client, upload_id, content, 0, 10, url=url, extra_headers={"HTTP_AUTHORIZATION": f"Bearer {token}"}, ) assert part_1_response.status_code == 201 part_2_response = create_partial_upload_file_request( client, upload_id, content, 10, len(content) // 2, url=url, extra_headers={"HTTP_AUTHORIZATION": f"Bearer {token}"}, ) assert part_2_response.status_code == 201 part_3_response = create_partial_upload_file_request( client, upload_id, content, len(content) // 2, len(content), url=url, extra_headers={"HTTP_AUTHORIZATION": f"Bearer {token}"}, ) assert part_3_response.status_code == 201 parsed_json = part_3_response.json() staged_file = StagedAjaxFile(uuid.UUID(parsed_json[0]["uuid"])) with staged_file.open() as f: staged_content = f.read() assert len(staged_content) == len(content) assert hash(staged_content) == hash(content) assert staged_content == content
def test_rfc7233_implementation_client_api(client): content = load_test_data() upload_id = generate_new_upload_id(test_rfc7233_implementation_client_api, content) token = Token.objects.create(user=UserFactory()) filename = "whatever.bin" start_byte = 0 content_io = BytesIO(content) max_chunk_length = 2**15 assert len(content) > 3 * max_chunk_length while True: chunk = content_io.read(max_chunk_length) if not chunk: break end_byte = start_byte + len(chunk) response = client.post( path=reverse("api:staged-file-list"), data={ filename: BytesIO(chunk), "X-Upload-ID": upload_id }, format="multipart", HTTP_CONTENT_RANGE= f"bytes {start_byte}-{end_byte - 1}/{len(content)}", HTTP_AUTHORIZATION=f"Token {token}", ) assert response.status_code == 201 start_byte += len(chunk) parsed_json = response.json() staged_file = StagedAjaxFile(uuid.UUID(parsed_json[0]["uuid"])) with staged_file.open() as f: staged_content = f.read() assert len(staged_content) == len(content) assert hash(staged_content) == hash(content) assert staged_content == content
def test_wrong_upload_headers_rfc7233(rf: RequestFactory): widget = AjaxUploadWidget(ajax_target_path="/ajax") widget.timeout = timedelta(seconds=1) content = load_test_data() upload_id = generate_new_upload_id(test_wrong_upload_headers_rfc7233, content) post_request = create_partial_upload_file_request(rf, upload_id, content, 0, 10) assert isinstance(widget.handle_ajax(post_request), JsonResponse) post_request = create_partial_upload_file_request(rf, upload_id, content, 0, 10) post_request.META["X-Upload-ID"] = None post_request = force_post_update(post_request, "X-Upload-ID", None) assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request(rf, upload_id, content, 0, 10) post_request.META[ "HTTP_CONTENT_RANGE"] = "corrupted data: 54343-3223/21323" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request(rf, upload_id, content, 0, 10) post_request.META["HTTP_CONTENT_RANGE"] = "bytes 54343-3223/21323" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request(rf, upload_id, content, 0, 10) post_request.META["HTTP_CONTENT_RANGE"] = "bytes 54343-3223/*" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request(rf, upload_id, content, 0, 10) post_request.META["HTTP_CONTENT_RANGE"] = "bytes 1000-3000/2000" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request(rf, upload_id, content, 0, 10) post_request.META["HTTP_CONTENT_RANGE"] = "bytes 1000-2000/*" assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest) post_request = create_partial_upload_file_request(rf, upload_id, content, 0, 10) post_request.META["X-Upload-ID"] = "a" * 1000 post_request = force_post_update(post_request, "X-Upload-ID", "a" * 1000) assert isinstance(widget.handle_ajax(post_request), HttpResponseBadRequest)
def test_rfc7233_implementation(rf: RequestFactory): content = load_test_data() upload_id = generate_new_upload_id(test_rfc7233_implementation, content) part_1 = create_partial_upload_file_request(rf, upload_id, content, 0, 10) part_2 = create_partial_upload_file_request(rf, upload_id, content, 10, len(content) // 2) part_3 = create_partial_upload_file_request(rf, upload_id, content, len(content) // 2, len(content)) widget = AjaxUploadWidget(ajax_target_path="/ajax") widget.timeout = timedelta(seconds=1) response = widget.handle_ajax(part_1) assert isinstance(response, JsonResponse) response = widget.handle_ajax(part_2) assert isinstance(response, JsonResponse) response = widget.handle_ajax(part_3) assert isinstance(response, JsonResponse) parsed_json = json.loads(response.content) staged_file = StagedAjaxFile(uuid.UUID(parsed_json[0]["uuid"])) with staged_file.open() as f: staged_content = f.read() assert staged_content == content
def test_rfc7233_implementation(rf: RequestFactory): content = load_test_data() upload_id = generate_new_upload_id(test_rfc7233_implementation, content) part_1 = create_partial_upload_file_request(rf, upload_id, content, 0, 10) part_2 = create_partial_upload_file_request( rf, upload_id, content, 10, len(content) // 2 ) part_3 = create_partial_upload_file_request( rf, upload_id, content, len(content) // 2, len(content) ) widget = AjaxUploadWidget(ajax_target_path="/ajax") widget.timeout = timedelta(seconds=1) response = widget.handle_ajax(part_1) assert isinstance(response, JsonResponse) response = widget.handle_ajax(part_2) assert isinstance(response, JsonResponse) response = widget.handle_ajax(part_3) assert isinstance(response, JsonResponse) parsed_json = json.loads(response.content) staged_file = StagedAjaxFile(uuid.UUID(parsed_json[0]["uuid"])) with staged_file.open() as f: staged_content = f.read() assert staged_content == content
def test_inconsistent_chunks_rfc7233(rf: RequestFactory): widget = AjaxUploadWidget(ajax_target_path="/ajax") widget.timeout = timedelta(seconds=1) content = load_test_data() # Overlapping chunks upload_id = generate_new_upload_id(test_inconsistent_chunks_rfc7233, content) part_1 = create_partial_upload_file_request(rf, upload_id, content, 0, 10) part_2 = create_partial_upload_file_request(rf, upload_id, content, 5, 15) widget.handle_ajax(part_1) assert isinstance(widget.handle_ajax(part_2), HttpResponseBadRequest) # Inconsistent filenames upload_id += "x" part_1 = create_partial_upload_file_request(rf, upload_id, content, 0, 10, filename="a") part_2 = create_partial_upload_file_request(rf, upload_id, content, 10, 20, filename="b") widget.handle_ajax(part_1) assert isinstance(widget.handle_ajax(part_2), HttpResponseBadRequest) # Inconsistent total size upload_id += "x" part_1 = create_partial_upload_file_request(rf, upload_id, content[:20], 0, 10) part_2 = create_partial_upload_file_request(rf, upload_id, content[:20], 10, 20) part_1.META["HTTP_CONTENT_RANGE"] = f"bytes 0-9/20" part_2.META["HTTP_CONTENT_RANGE"] = f"bytes 10-19/30" widget.handle_ajax(part_1) assert isinstance(widget.handle_ajax(part_2), HttpResponseBadRequest)
def test_upload_validator_using_wrong_extension(rf: RequestFactory): widget = AjaxUploadWidget( ajax_target_path="/ajax", upload_validators=[ ExtensionValidator(allowed_extensions=('.allowed-extension', )) ], ) widget.timeout = timedelta(seconds=1) content = load_test_data() upload_id = generate_new_upload_id( test_upload_validator_using_wrong_extension, content) request = create_upload_file_request(rf, content=b"should error", filename="test.wrong_extension") response = widget.handle_ajax(request) assert response.status_code == 403 request = create_upload_file_request(rf, content=b"should error", filename="test.allowed-extension") response = widget.handle_ajax(request) assert response.status_code == 200
def test_inconsistent_chunks_rfc7233(client): content = load_test_data() url = reverse("api:staged-file-list") token = Token.objects.create(user=UserFactory()) # Overlapping chunks upload_id = generate_new_upload_id(test_inconsistent_chunks_rfc7233, content) part_1 = create_partial_upload_file_request( client, upload_id, content, 0, 10, url=url, extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert part_1.status_code == 201 part_2 = create_partial_upload_file_request( client, upload_id, content, 5, 15, url=url, extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert part_2.status_code == 400 # Inconsistent filenames upload_id += "x" part_1 = create_partial_upload_file_request( client, upload_id, content, 0, 10, filename="a", url=url, extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert part_1.status_code == 201 part_2 = create_partial_upload_file_request( client, upload_id, content, 10, 20, filename="b", url=url, extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert part_2.status_code == 400 # Inconsistent total size upload_id += "x" part_1 = create_partial_upload_file_request( client, upload_id, content[:20], 0, 10, url=url, http_content_range="bytes 0-9/20", extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert part_1.status_code == 201 part_2 = create_partial_upload_file_request( client, upload_id, content[:20], 10, 20, url=url, http_content_range="bytes 10-19/30", extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert part_2.status_code == 400
def test_wrong_upload_headers_rfc7233_api(client): content = load_test_data() upload_id = generate_new_upload_id(test_wrong_upload_headers_rfc7233_api, content) url = reverse("api:staged-file-list") token = Token.objects.create(user=UserFactory()) response = create_partial_upload_file_request( client, upload_id, content, 0, 10, url=url, extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert response.status_code == 201 response = create_partial_upload_file_request( client, None, content, 0, 10, url=url, extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert response.status_code == 400 response = create_partial_upload_file_request( client, upload_id, content, 0, 10, url=url, http_content_range="corrupted data: 54343-3223/21323", extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert response.status_code == 400 response = create_partial_upload_file_request( client, upload_id, content, 0, 10, url=url, http_content_range="bytes 54343-3223/21323", extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert response.status_code == 400 response = create_partial_upload_file_request( client, upload_id, content, 0, 10, url=url, http_content_range="bytes 54343-3223/*", extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert response.status_code == 400 response = create_partial_upload_file_request( client, upload_id, content, 0, 10, url=url, http_content_range="bytes 1000-3000/2000", extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert response.status_code == 400 response = create_partial_upload_file_request( client, upload_id, content, 0, 10, url=url, http_content_range="bytes 1000-2000/*", extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert response.status_code == 400 response = create_partial_upload_file_request( client, "a" * 1000, content, 0, 10, url=url, extra_headers={"HTTP_AUTHORIZATION": f"Token {token}"}, ) assert response.status_code == 400