1import pytest 2 3from backend.config import StorageSettings 4 5 6@pytest.fixture 7def storage_settings(monkeypatch: pytest.MonkeyPatch) -> StorageSettings: 8 """fixture for storage settings with R2 image bucket configured.""" 9 monkeypatch.setenv( 10 "R2_PUBLIC_IMAGE_BUCKET_URL", "https://images.example.com/bucket" 11 ) 12 return StorageSettings() 13 14 15def test_validate_image_url_allows_none(storage_settings: StorageSettings) -> None: 16 """validate that None/empty imageUrl is allowed.""" 17 assert storage_settings.validate_image_url(None) is True 18 assert storage_settings.validate_image_url("") is True 19 20 21def test_validate_image_url_allows_trusted_origin( 22 storage_settings: StorageSettings, 23) -> None: 24 """validate that imageUrl from allowed origin passes.""" 25 url = "https://images.example.com/bucket/track123.jpg" 26 assert storage_settings.validate_image_url(url) is True 27 28 29def test_validate_image_url_rejects_external_origin( 30 storage_settings: StorageSettings, 31) -> None: 32 """validate that imageUrl from external origin is rejected.""" 33 url = "https://malicious.com/bad-image.jpg" 34 35 with pytest.raises(ValueError, match="image must be hosted on allowed origins"): 36 storage_settings.validate_image_url(url) 37 38 39def test_validate_image_url_rejects_subdomain_mismatch( 40 storage_settings: StorageSettings, 41) -> None: 42 """validate that subdomains are not automatically trusted.""" 43 url = "https://evil.images.example.com/fake.jpg" 44 45 with pytest.raises(ValueError, match="image must be hosted on allowed origins"): 46 storage_settings.validate_image_url(url) 47 48 49def test_validate_image_url_respects_scheme(storage_settings: StorageSettings) -> None: 50 """validate that scheme (http vs https) is enforced.""" 51 url = "http://images.example.com/bucket/track123.jpg" 52 53 with pytest.raises(ValueError, match="image must be hosted on allowed origins"): 54 storage_settings.validate_image_url(url) 55 56 57def test_allowed_image_origins_empty_when_no_bucket_configured( 58 monkeypatch: pytest.MonkeyPatch, 59) -> None: 60 """validate that allowed_image_origins is empty without R2 config.""" 61 monkeypatch.setenv("R2_PUBLIC_IMAGE_BUCKET_URL", "") 62 settings = StorageSettings() 63 assert settings.allowed_image_origins == set() 64 65 66def test_allowed_image_origins_extracts_origin( 67 monkeypatch: pytest.MonkeyPatch, 68) -> None: 69 """validate that allowed_image_origins correctly extracts scheme+netloc.""" 70 monkeypatch.setenv( 71 "R2_PUBLIC_IMAGE_BUCKET_URL", "https://cdn.example.com/my-bucket/path" 72 ) 73 settings = StorageSettings() 74 assert settings.allowed_image_origins == {"https://cdn.example.com"}