mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-03-23 01:53:32 +08:00
Make asset mime_type immutable after first ingest
Prevents cross-tenant metadata mutation when multiple references share the same content-addressed Asset row. mime_type can now only be set when NULL (first ingest); subsequent attempts to change it are silently ignored. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
bec0e709f0
commit
0ba183aed7
@ -69,7 +69,7 @@ def upsert_asset(
|
|||||||
if asset.size_bytes != int(size_bytes) and int(size_bytes) > 0:
|
if asset.size_bytes != int(size_bytes) and int(size_bytes) > 0:
|
||||||
asset.size_bytes = int(size_bytes)
|
asset.size_bytes = int(size_bytes)
|
||||||
changed = True
|
changed = True
|
||||||
if mime_type and asset.mime_type != mime_type:
|
if mime_type and not asset.mime_type:
|
||||||
asset.mime_type = mime_type
|
asset.mime_type = mime_type
|
||||||
changed = True
|
changed = True
|
||||||
if changed:
|
if changed:
|
||||||
@ -118,7 +118,7 @@ def update_asset_hash_and_mime(
|
|||||||
return False
|
return False
|
||||||
if asset_hash is not None:
|
if asset_hash is not None:
|
||||||
asset.hash = asset_hash
|
asset.hash = asset_hash
|
||||||
if mime_type is not None:
|
if mime_type is not None and not asset.mime_type:
|
||||||
asset.mime_type = mime_type
|
asset.mime_type = mime_type
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@ -108,10 +108,11 @@ def update_asset_metadata(
|
|||||||
touched = True
|
touched = True
|
||||||
|
|
||||||
if mime_type is not None:
|
if mime_type is not None:
|
||||||
update_asset_hash_and_mime(
|
updated = update_asset_hash_and_mime(
|
||||||
session, asset_id=ref.asset_id, mime_type=mime_type
|
session, asset_id=ref.asset_id, mime_type=mime_type
|
||||||
)
|
)
|
||||||
touched = True
|
if updated:
|
||||||
|
touched = True
|
||||||
|
|
||||||
if preview_id is not None:
|
if preview_id is not None:
|
||||||
set_reference_preview(
|
set_reference_preview(
|
||||||
|
|||||||
@ -146,7 +146,7 @@ def _register_existing_asset(
|
|||||||
if not asset:
|
if not asset:
|
||||||
raise ValueError(f"No asset with hash {asset_hash}")
|
raise ValueError(f"No asset with hash {asset_hash}")
|
||||||
|
|
||||||
if mime_type and asset.mime_type != mime_type:
|
if mime_type and not asset.mime_type:
|
||||||
update_asset_hash_and_mime(session, asset_id=asset.id, mime_type=mime_type)
|
update_asset_hash_and_mime(session, asset_id=asset.id, mime_type=mime_type)
|
||||||
|
|
||||||
if preview_id:
|
if preview_id:
|
||||||
|
|||||||
@ -10,6 +10,7 @@ from app.assets.database.queries import (
|
|||||||
get_asset_by_hash,
|
get_asset_by_hash,
|
||||||
upsert_asset,
|
upsert_asset,
|
||||||
bulk_insert_assets,
|
bulk_insert_assets,
|
||||||
|
update_asset_hash_and_mime,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -142,3 +143,45 @@ class TestBulkInsertAssets:
|
|||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
assert session.query(Asset).count() == 200
|
assert session.query(Asset).count() == 200
|
||||||
|
|
||||||
|
|
||||||
|
class TestMimeTypeImmutability:
|
||||||
|
"""mime_type on Asset is write-once: set on first ingest, never overwritten."""
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"initial_mime,second_mime,expected_mime",
|
||||||
|
[
|
||||||
|
("image/png", "image/jpeg", "image/png"),
|
||||||
|
(None, "image/png", "image/png"),
|
||||||
|
],
|
||||||
|
ids=["preserves_existing", "fills_null"],
|
||||||
|
)
|
||||||
|
def test_upsert_mime_immutability(self, session: Session, initial_mime, second_mime, expected_mime):
|
||||||
|
h = f"blake3:upsert_{initial_mime}_{second_mime}"
|
||||||
|
upsert_asset(session, asset_hash=h, size_bytes=100, mime_type=initial_mime)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
asset, created, _ = upsert_asset(session, asset_hash=h, size_bytes=100, mime_type=second_mime)
|
||||||
|
assert created is False
|
||||||
|
assert asset.mime_type == expected_mime
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"initial_mime,update_mime,update_hash,expected_mime,expected_hash",
|
||||||
|
[
|
||||||
|
(None, "image/png", None, "image/png", "blake3:upd0"),
|
||||||
|
("image/png", "image/jpeg", None, "image/png", "blake3:upd1"),
|
||||||
|
("image/png", "image/jpeg", "blake3:upd2_new", "image/png", "blake3:upd2_new"),
|
||||||
|
],
|
||||||
|
ids=["fills_null", "preserves_existing", "hash_updates_mime_locked"],
|
||||||
|
)
|
||||||
|
def test_update_asset_hash_and_mime_immutability(
|
||||||
|
self, session: Session, initial_mime, update_mime, update_hash, expected_mime, expected_hash,
|
||||||
|
):
|
||||||
|
h = expected_hash.removesuffix("_new")
|
||||||
|
asset = Asset(hash=h, size_bytes=100, mime_type=initial_mime)
|
||||||
|
session.add(asset)
|
||||||
|
session.flush()
|
||||||
|
|
||||||
|
update_asset_hash_and_mime(session, asset_id=asset.id, mime_type=update_mime, asset_hash=update_hash)
|
||||||
|
assert asset.mime_type == expected_mime
|
||||||
|
assert asset.hash == expected_hash
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user