from __future__ import annotations from pathlib import Path from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from app.api.deps import CurrentUserContext from app.core.config import Settings, get_settings from app.core import secret_box from app.db.base import Base from app.models.system_model_setting import SystemModelSetting from app.models.system_setting import SystemSetting from app.models.system_setting_secret import SystemSettingSecret from app.schemas.settings import SettingsWrite from app.services.knowledge import KnowledgeService from app.services.settings import SettingsService def build_session_factory(db_file: Path): engine = create_engine( f"sqlite+pysqlite:///{db_file.as_posix()}", connect_args={"check_same_thread": False}, ) SystemSetting.__table__.create(bind=engine) SystemSettingSecret.__table__.create(bind=engine) SystemModelSetting.__table__.create(bind=engine) return sessionmaker(bind=engine, autoflush=False, autocommit=False) def test_onlyoffice_config_is_read_only_for_admin_users(tmp_path, monkeypatch) -> None: env_file = tmp_path / ".env" env_file.write_text( "\n".join( [ "ONLYOFFICE_ENABLED=true", "ONLYOFFICE_PUBLIC_URL=http://10.10.10.122:8082", "ONLYOFFICE_BACKEND_URL=http://main:8000", "ONLYOFFICE_JWT_SECRET=change-me-onlyoffice", ] ) + "\n", encoding="utf-8", ) original_env_file = Settings.model_config.get("env_file") monkeypatch.setitem(Settings.model_config, "env_file", (env_file,)) get_settings.cache_clear() try: service = KnowledgeService(storage_root=tmp_path) service.ensure_library_ready() document_id = "readonly-docx" folder = "制度政策" stored_name = f"{document_id}__制度预览.docx" target_path = tmp_path / "knowledge" / folder / stored_name target_path.write_bytes(b"fake-docx-content") current_user = CurrentUserContext( username="admin", name="管理员", role_codes=["manager"], is_admin=True, ) config = service.build_onlyoffice_config(document_id, current_user) permissions = config.config["document"]["permissions"] customization = config.config["editorConfig"]["customization"] assert config.documentServerUrl == "http://10.10.10.122:8082" assert config.config["editorConfig"]["mode"] == "view" assert permissions["edit"] is False assert permissions["download"] is True assert customization["autosave"] is False assert customization["forcesave"] is False finally: monkeypatch.setitem(Settings.model_config, "env_file", original_env_file) get_settings.cache_clear() def test_onlyoffice_config_prefers_saved_settings_snapshot(tmp_path, monkeypatch) -> None: env_file = tmp_path / ".env" env_file.write_text( "\n".join( [ "ADMIN_EMAIL=admin@example.com", "ONLYOFFICE_ENABLED=false", "ONLYOFFICE_BACKEND_URL=http://main:8000", ] ) + "\n", encoding="utf-8", ) original_env_file = Settings.model_config.get("env_file") monkeypatch.setitem(Settings.model_config, "env_file", (env_file,)) monkeypatch.setattr(secret_box, "SECRET_KEY_FILE", tmp_path / "settings.key") monkeypatch.setattr(Base.metadata, "create_all", lambda *args, **kwargs: None) get_settings.cache_clear() session_factory = build_session_factory(tmp_path / "settings.db") monkeypatch.setattr("app.services.settings.get_session_factory", lambda: session_factory) try: with session_factory() as db: service = SettingsService(db) payload = service.get_settings_snapshot().model_dump() payload["renderForm"]["enabled"] = True payload["renderForm"]["publicUrl"] = "http://10.10.10.122:8082" payload["renderForm"]["jwtSecret"] = "change-me-onlyoffice" service.save_settings_snapshot(SettingsWrite(**payload)) service = KnowledgeService(storage_root=tmp_path) service.ensure_library_ready() document_id = "db-backed-docx" folder = "制度政策" stored_name = f"{document_id}__制度预览.docx" target_path = tmp_path / "knowledge" / folder / stored_name target_path.write_bytes(b"fake-docx-content") current_user = CurrentUserContext( username="admin", name="管理员", role_codes=["manager"], is_admin=True, ) config = service.build_onlyoffice_config(document_id, current_user) assert config.documentServerUrl == "http://10.10.10.122:8082" assert config.config["document"]["url"].startswith( "http://main:8000/api/v1/knowledge/documents/db-backed-docx/onlyoffice/content?access_token=" ) finally: monkeypatch.setitem(Settings.model_config, "env_file", original_env_file) get_settings.cache_clear()