152 lines
4.9 KiB
Python
152 lines
4.9 KiB
Python
from io import BytesIO
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
from starlette.datastructures import UploadFile
|
|
|
|
from app.gateway.routers import app_identity as app_identity_router
|
|
from deerflow.config.system_settings import AppIdentitySettings, SystemSettings
|
|
|
|
PNG = bytes.fromhex(
|
|
"89504e470d0a1a0a0000000d49484452000000010000000108060000001f15c4"
|
|
"890000000a49444154789c63000100000500010d0a2db40000000049454e44ae426082"
|
|
)
|
|
|
|
|
|
def _store(monkeypatch: pytest.MonkeyPatch, tmp_path):
|
|
current = {"settings": SystemSettings()}
|
|
|
|
def load():
|
|
return current["settings"]
|
|
|
|
def save(settings: SystemSettings) -> SystemSettings:
|
|
current["settings"] = settings
|
|
return settings
|
|
|
|
async def admin_user(_request):
|
|
return SimpleNamespace(system_role="admin")
|
|
|
|
monkeypatch.setattr(app_identity_router, "runtime_home", lambda: tmp_path)
|
|
monkeypatch.setattr("deerflow.config.system_settings.runtime_home", lambda: tmp_path)
|
|
monkeypatch.setattr(app_identity_router, "load_system_settings", load)
|
|
monkeypatch.setattr(app_identity_router, "save_system_settings", save)
|
|
monkeypatch.setattr("deerflow.config.system_settings.load_system_settings", load)
|
|
monkeypatch.setattr(
|
|
"app.gateway.routers.system_settings.get_optional_user_from_request",
|
|
admin_user,
|
|
)
|
|
return current
|
|
|
|
|
|
def test_new_settings_leave_app_identity_empty() -> None:
|
|
assert SystemSettings().app_identity == AppIdentitySettings()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_non_admin_cannot_change_app_identity(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
async def ordinary_user(_request):
|
|
return SimpleNamespace(system_role="user")
|
|
|
|
monkeypatch.setattr(
|
|
"app.gateway.routers.system_settings.get_optional_user_from_request",
|
|
ordinary_user,
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as error:
|
|
await app_identity_router.update_app_identity_settings(
|
|
SimpleNamespace(),
|
|
system_name="新系统",
|
|
remove_logo=False,
|
|
logo=None,
|
|
)
|
|
|
|
assert error.value.status_code == 403
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_admin_saves_name_without_replacing_the_static_logo(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
tmp_path,
|
|
) -> None:
|
|
current = _store(monkeypatch, tmp_path)
|
|
|
|
response = await app_identity_router.update_app_identity_settings(
|
|
SimpleNamespace(),
|
|
system_name=" 研判中心 ",
|
|
remove_logo=False,
|
|
logo=None,
|
|
)
|
|
|
|
assert response.system_name == "研判中心"
|
|
assert response.has_logo is False
|
|
assert response.logo_url is None
|
|
assert current["settings"].app_identity.logo_filename is None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_uploaded_logo_is_served_separately_from_generated_pages(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
tmp_path,
|
|
) -> None:
|
|
current = _store(monkeypatch, tmp_path)
|
|
upload = UploadFile(file=BytesIO(PNG), filename="mark.png")
|
|
|
|
saved = await app_identity_router.update_app_identity_settings(
|
|
SimpleNamespace(),
|
|
system_name="研判中心",
|
|
remove_logo=False,
|
|
logo=upload,
|
|
)
|
|
|
|
assert saved.has_logo is True
|
|
assert saved.logo_url is not None
|
|
assert saved.logo_url.startswith("/api/public/app-identity/logo?v=")
|
|
logo_file = tmp_path / "app-identity" / current["settings"].app_identity.logo_filename
|
|
assert logo_file.is_file()
|
|
assert not (tmp_path / "generated-page-branding").exists()
|
|
|
|
served = await app_identity_router.get_app_identity_logo()
|
|
assert served.media_type == "image/png"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_invalid_logo_is_rejected(monkeypatch: pytest.MonkeyPatch, tmp_path) -> None:
|
|
_store(monkeypatch, tmp_path)
|
|
upload = UploadFile(file=BytesIO(b"not-an-image"), filename="mark.gif")
|
|
|
|
with pytest.raises(HTTPException) as error:
|
|
await app_identity_router.update_app_identity_settings(
|
|
SimpleNamespace(),
|
|
system_name="研判中心",
|
|
remove_logo=False,
|
|
logo=upload,
|
|
)
|
|
|
|
assert error.value.status_code == 422
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_clearing_app_identity_removes_only_its_logo(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
tmp_path,
|
|
) -> None:
|
|
current = _store(monkeypatch, tmp_path)
|
|
upload = UploadFile(file=BytesIO(PNG), filename="mark.png")
|
|
await app_identity_router.update_app_identity_settings(
|
|
SimpleNamespace(),
|
|
system_name="研判中心",
|
|
remove_logo=False,
|
|
logo=upload,
|
|
)
|
|
logo_file = tmp_path / "app-identity" / current["settings"].app_identity.logo_filename
|
|
|
|
cleared = await app_identity_router.delete_app_identity_settings(SimpleNamespace())
|
|
|
|
assert cleared.system_name == ""
|
|
assert cleared.has_logo is False
|
|
assert logo_file.exists() is False
|
|
with pytest.raises(HTTPException) as error:
|
|
await app_identity_router.get_app_identity_logo()
|
|
assert error.value.status_code == 404
|