Files
pigway-frame-flow/tests/test_audit_fixes.py
T
渡口浪人 1494904b12
Community checks / verify (push) Skipped
Verify Frame Flow / verify (push) Successful in 8m9s
fix: close library upload flow and harden image storage
2026-10-24 00:38:00 +08:00

130 lines
4.4 KiB
Python

import shutil
import pytest
def test_image_write_permission_can_be_granted_without_admin(client):
from io import BytesIO
from PIL import Image
data = BytesIO()
Image.new("RGB", (30, 20), "green").save(data, "PNG")
picture = client.post(
"/api/v1/source-libraries/manual-uploads/upload",
files={"file": ("fixture.png", data.getvalue())},
).json()
scopes = client.get("/api/v1/client-scopes").json()
assert "images:write" in scopes
response = client.post(
"/api/v1/clients",
json={
"client_id": "image-writer",
"name": "Writer",
"permissions": ["images:write"],
},
)
assert response.status_code == 201
client.headers["Authorization"] = "Bearer " + response.json()["token"]
# Authorization succeeds and resource lookup fails; administrative routes stay forbidden.
assert (
client.put("/api/v1/assets/missing/star", json={"starred": True}).status_code
== 404
)
assert (
client.put(
"/api/v1/source-images/" + picture["id"] + "/star", json={"starred": True}
).status_code
== 200
)
assert (
client.put(
"/api/v1/source-images/" + picture["id"] + "/exclusion",
json={"excluded": True},
).status_code
== 409
)
assert client.get("/api/v1/clients").status_code == 403
def test_nested_transaction_rollback_includes_execute(service):
with pytest.raises(RuntimeError):
with service.db.transaction():
service.db.execute("INSERT INTO app_config VALUES('outer','{}')")
with service.db.transaction():
service.db.execute("INSERT INTO app_config VALUES('inner','{}')")
raise RuntimeError("injected failure")
assert (
service.db.one("SELECT key FROM app_config WHERE key IN ('outer','inner')")
is None
)
def test_low_disk_space_is_reported_without_enabling_cleanup(client, monkeypatch):
monkeypatch.setattr(
shutil,
"disk_usage",
lambda _path: shutil._ntuple_diskusage(100 * 1024**3, 99 * 1024**3, 1024**3),
)
data = client.get("/api/v1/storage").json()
assert data["disk"]["low_space"] is True
assert data["disk"]["free_bytes"] == 1024**3
assert data["policy"]["enabled"] is False
def test_unsupported_image_plugin_is_never_invoked(monkeypatch):
from PIL import Image
from pigway_frame_flow.errors import FlowError
from pigway_frame_flow.renderers.images import convert
Image.init()
invoked = []
def vulnerable_plugin(*_args):
invoked.append(True)
raise RuntimeError("Unsupported plugin must not parse input")
monkeypatch.setitem(Image.OPEN, "XBM", (vulnerable_plugin, lambda _prefix: True))
with pytest.raises(FlowError):
convert(b"#define image_width 1\n#define image_height 1\n")
assert not invoked
def test_promotion_sql_failure_keeps_original_cache(service, monkeypatch):
asset = service.assets.put(b"fixture", "cached.jpg", "cache")
original = service.db.execute
def fail(query, args=()):
if query.startswith("UPDATE assets SET kind"):
raise RuntimeError("injected promotion SQL failure")
return original(query, args)
monkeypatch.setattr(service.db, "execute", fail)
with pytest.raises(RuntimeError):
service.assets.promote(asset["asset_id"])
assert service.assets.path(asset["asset_id"]).parent.name == "cache"
assert service.assets.path(asset["asset_id"]).read_bytes() == b"fixture"
assert not list((service.settings.data_dir / "images").iterdir())
assert not service.db.all("SELECT * FROM asset_file_moves")
def test_promotion_restart_finishes_committed_move(service):
from pigway_frame_flow.renderers.images import Assets
asset = service.assets.put(b"fixture", "cached.jpg", "cache")
source = service.assets.path(asset["asset_id"])
target = service.settings.data_dir / "images" / source.name
target.write_bytes(source.read_bytes())
service.db.execute(
"INSERT INTO asset_file_moves VALUES(?,?,?)",
(asset["asset_id"], "cache", "images"),
)
service.db.execute(
"UPDATE assets SET kind='images' WHERE id=?", (asset["asset_id"],)
)
Assets(service.db, service.settings)
assert not source.exists()
assert service.assets.path(asset["asset_id"]).read_bytes() == b"fixture"
assert not service.db.all("SELECT * FROM asset_file_moves")