diff --git a/src/upload_handler.py b/src/upload_handler.py index 0937a14..7396a6a 100644 --- a/src/upload_handler.py +++ b/src/upload_handler.py @@ -31,7 +31,11 @@ import logging logger = logging.getLogger(__name__) -UPLOAD_ID_RE = re.compile(r"^[0-9a-fA-F]{32}\.[A-Za-z0-9]+$") +# The extension is optional: save_upload builds the id as `{uuid.hex}{ext}`, +# and a file with no extension (Dockerfile, README, ...) yields a bare 32-hex +# id. Requiring `.ext` made those ids fail validation, so the stored file +# could never be resolved or downloaded again. +UPLOAD_ID_RE = re.compile(r"^[0-9a-fA-F]{32}(?:\.[A-Za-z0-9]+)?$") def is_valid_upload_id(upload_id: str) -> bool: diff --git a/tests/test_upload_id_validation.py b/tests/test_upload_id_validation.py new file mode 100644 index 0000000..69e8535 --- /dev/null +++ b/tests/test_upload_id_validation.py @@ -0,0 +1,21 @@ +"""Tests for upload id validation (src/upload_handler.py).""" +import uuid + +from src.upload_handler import is_valid_upload_id + + +def test_extensionless_id_is_valid(): + # save_upload builds `{uuid.hex}{ext}`; a file with no extension yields a + # bare 32-hex id, which used to fail validation and become unresolvable. + assert is_valid_upload_id(uuid.uuid4().hex) is True + + +def test_id_with_extension_still_valid(): + assert is_valid_upload_id(uuid.uuid4().hex + ".png") is True + + +def test_invalid_ids_rejected(): + assert is_valid_upload_id("not-an-id") is False + assert is_valid_upload_id(uuid.uuid4().hex + ".") is False + assert is_valid_upload_id("") is False + assert is_valid_upload_id(uuid.uuid4().hex + ".tar.gz") is False