from base64 import b64encode from hashlib import sha1 from hmac import new as hmac_new from types import SimpleNamespace from urllib.parse import parse_qs, urlsplit from app import media_urls def test_sign_oss_get_url_uses_oss_v1_query_signature(): url = "https://one-feel-ota-data.oss-cn-guangzhou.aliyuncs.com/admin/site-config/image.webp" signed = media_urls.sign_oss_get_url( url, access_key_id="test-access-key", access_key_secret="test-access-secret", endpoint="oss-cn-guangzhou.aliyuncs.com", bucket="one-feel-ota-data", expires_at=1_800_000_000, ) parsed = urlsplit(signed) query = parse_qs(parsed.query) string_to_sign = "GET\n\n\n1800000000\n/one-feel-ota-data/admin/site-config/image.webp" expected_signature = b64encode( hmac_new(b"test-access-secret", string_to_sign.encode("utf-8"), sha1).digest() ).decode("ascii") assert parsed.path == "/admin/site-config/image.webp" assert query["OSSAccessKeyId"] == ["test-access-key"] assert query["Expires"] == ["1800000000"] assert query["Signature"] == [expected_signature] def test_resolve_media_url_only_signs_the_configured_oss_host(monkeypatch): monkeypatch.setattr( media_urls, "get_settings", lambda: SimpleNamespace( oss_access_key_id="test-access-key", oss_access_key_secret="test-access-secret", oss_endpoint="oss-cn-guangzhou.aliyuncs.com", oss_public_base_url="https://one-feel-ota-data.oss-cn-guangzhou.aliyuncs.com", oss_bucket_name="one-feel-ota-data", ), ) monkeypatch.setattr(media_urls, "time", lambda: 1_800_000_000) oss_url = "https://one-feel-ota-data.oss-cn-guangzhou.aliyuncs.com/admin/image.webp" external_url = "https://cdn.example.test/image.webp" signed = media_urls.resolve_media_url(oss_url) assert signed != oss_url assert "OSSAccessKeyId=test-access-key" in signed assert media_urls.resolve_media_url(external_url) == external_url def test_resolve_media_url_rewrites_legacy_internal_oss_host_before_signing(monkeypatch): monkeypatch.setattr( media_urls, "get_settings", lambda: SimpleNamespace( oss_access_key_id="test-access-key", oss_access_key_secret="test-access-secret", oss_endpoint="oss-cn-guangzhou-internal.aliyuncs.com", oss_public_base_url="https://one-feel-ota-data.oss-cn-guangzhou.aliyuncs.com", oss_bucket_name="one-feel-ota-data", ), ) monkeypatch.setattr(media_urls, "time", lambda: 1_800_000_000) legacy_url = "https://one-feel-ota-data.oss-cn-guangzhou-internal.aliyuncs.com/admin/image.webp" signed = media_urls.resolve_media_url(legacy_url) parsed = urlsplit(signed) assert parsed.netloc == "one-feel-ota-data.oss-cn-guangzhou.aliyuncs.com" assert parsed.path == "/admin/image.webp" assert parse_qs(parsed.query)["OSSAccessKeyId"] == ["test-access-key"] def test_resolve_media_fields_signs_common_image_fields(monkeypatch): monkeypatch.setattr( "app.serializers.resolve_media_url", lambda value: f"signed:{value}" if value else value, ) from app.serializers import resolve_media_fields result = resolve_media_fields( { "image": "oss-image", "avatar": "oss-avatar", "qrImage": "oss-qr", "url": "oss-url", "gallery": ["oss-gallery-1", "oss-gallery-2"], "label": "unchanged", } ) assert result == { "image": "signed:oss-image", "avatar": "signed:oss-avatar", "qrImage": "signed:oss-qr", "url": "signed:oss-url", "gallery": ["signed:oss-gallery-1", "signed:oss-gallery-2"], "label": "unchanged", }