feat: allow admins to update audit checklist configuration
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
APP = (ROOT / "app" / "web_app_fastapi.py").read_text(encoding="utf-8")
|
||||
TEMPLATE = (ROOT / "app" / "templates" / "admin_tools.html").read_text(encoding="utf-8")
|
||||
COMPOSE = (ROOT / "docker-compose.yml").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_admin_checklist_upload_route_exists_and_is_admin_only():
|
||||
assert '@app.post("/admin/checklists/upload", name="admin_checklists_upload")' in APP
|
||||
assert "async def admin_upload_checklist_config(" in APP
|
||||
function = APP.split("async def admin_upload_checklist_config(", 1)[1].split("@app.", 1)[0]
|
||||
assert "require_admin_session(request)" in function
|
||||
|
||||
|
||||
def test_upload_uses_server_side_os_mapping_and_validates_json():
|
||||
function = APP.split("async def admin_upload_checklist_config(", 1)[1].split("@app.", 1)[0]
|
||||
assert "OS_CONFIG.get(os_type)" in function
|
||||
assert "normalize_json" in function
|
||||
assert "validate_xlsx" in function
|
||||
assert "install_config_files" in function
|
||||
|
||||
|
||||
def test_admin_ui_contains_checklist_configuration_form():
|
||||
assert "admin_checklists_upload" in TEMPLATE
|
||||
assert 'name="checklist_file"' in TEMPLATE
|
||||
assert 'name="config_file"' in TEMPLATE
|
||||
|
||||
|
||||
def test_config_mount_is_writable_for_persistent_uploads():
|
||||
assert "./config:/app/config:ro" not in COMPOSE
|
||||
assert "./config:/app/config" in COMPOSE
|
||||
@@ -0,0 +1,48 @@
|
||||
import io
|
||||
import json
|
||||
import tempfile
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
from app.config_upload import install_config_files, normalize_json, validate_xlsx
|
||||
|
||||
|
||||
def _minimal_xlsx() -> bytes:
|
||||
buffer = io.BytesIO()
|
||||
with zipfile.ZipFile(buffer, "w") as archive:
|
||||
archive.writestr("[Content_Types].xml", "<Types/>")
|
||||
archive.writestr("xl/workbook.xml", "<workbook/>")
|
||||
return buffer.getvalue()
|
||||
|
||||
|
||||
def test_validate_xlsx_accepts_workbook_zip():
|
||||
assert validate_xlsx(_minimal_xlsx()) == _minimal_xlsx()
|
||||
|
||||
|
||||
def test_validate_xlsx_rejects_arbitrary_pk_data():
|
||||
try:
|
||||
validate_xlsx(b"PK-not-a-real-xlsx")
|
||||
except ValueError as exc:
|
||||
assert "XLSX" in str(exc)
|
||||
else:
|
||||
raise AssertionError("invalid XLSX was accepted")
|
||||
|
||||
|
||||
def test_normalize_json_rejects_scalar_and_formats_object():
|
||||
assert json.loads(normalize_json(b'{"a":1}')) == {"a": 1}
|
||||
try:
|
||||
normalize_json(b'"scalar"')
|
||||
except ValueError as exc:
|
||||
assert "object" in str(exc)
|
||||
else:
|
||||
raise AssertionError("scalar JSON was accepted")
|
||||
|
||||
|
||||
def test_install_config_files_replaces_and_backs_up_existing_file():
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
target = root / "rules.json"
|
||||
target.write_bytes(b"old")
|
||||
install_config_files(root, [("rules.json", b"new")])
|
||||
assert target.read_bytes() == b"new"
|
||||
assert (root / "rules.json.bak").read_bytes() == b"old"
|
||||
Reference in New Issue
Block a user