fix(审计): 移除共享库审计与预览噪声

This commit is contained in:
Cheng Zhou
2026-07-16 15:29:26 +08:00
parent 6b55c18610
commit 88bd0c5942
13 changed files with 134 additions and 377 deletions
+22 -18
View File
@@ -674,24 +674,30 @@ def test_subject_audit_uses_structured_business_snapshot():
assert 'detail=f"参与者 {subject_id} 已删除"' not in delete_subject_source
def test_faq_audit_uses_business_descriptions():
"""医学咨询审计详情应使用业务描述,避免 FAQ 技术文案"""
def test_shared_library_does_not_write_audits():
"""共享库各模块及其附件不应写入业务审计"""
api_dir = Path(__file__).resolve().parents[1] / "app" / "api" / "v1"
category_source = (api_dir / "faq_categories.py").read_text()
item_source = (api_dir / "faqs.py").read_text()
services_dir = Path(__file__).resolve().parents[1] / "app" / "services"
non_audited_sources = [
(api_dir / "faq_categories.py").read_text(),
(api_dir / "faqs.py").read_text(),
(api_dir / "precautions.py").read_text(),
(services_dir / "collaboration_service.py").read_text(),
(services_dir / "collaboration_share_service.py").read_text(),
(services_dir / "onlyoffice_collaboration_service.py").read_text(),
]
assert 'description": f"创建“{category.name}”分类"' in category_source
assert 'description": f"更新“{updated.name}”分类"' in category_source
assert 'description": f"删除“{category_name}”分类"' in category_source
assert 'f"创建医学咨询问题“{question_name}"' in item_source
assert 'f"更新医学咨询问题“{question_name}"' in item_source
assert 'f"回复医学咨询问题“{question_name}"' in item_source
assert 'f"删除医学咨询问题“{question_name}"' in item_source
assert 'f"删除医学咨询问题“{question_name}”的回复"' in item_source
assert "FAQ 分类 {category.name} 已创建" not in category_source
assert 'detail="FAQ 已创建"' not in item_source
assert 'detail = "FAQ updated"' not in item_source
assert '"description": "创建医学咨询问题"' not in item_source
for source in non_audited_sources:
assert "audit_crud" not in source
assert "._audit(" not in source
attachment_source = (api_dir / "attachments.py").read_text()
assert 'SHARED_LIBRARY_ENTITY_TYPES = {"precaution", "faq_replies"}' in attachment_source
assert "if entity_type not in SHARED_LIBRARY_ENTITY_TYPES:" in attachment_source
assert "if attachment.entity_type not in SHARED_LIBRARY_ENTITY_TYPES:" in attachment_source
onlyoffice_source = (api_dir / "onlyoffice.py").read_text()
assert "OFFICE_PREVIEW_OPEN" not in onlyoffice_source
def test_domain_audits_use_business_object_names():
@@ -704,7 +710,6 @@ def test_domain_audits_use_business_object_names():
"material_equipments.py",
"visits.py",
"aes.py",
"precautions.py",
"fees_contracts.py",
"startup.py",
"subject_histories.py",
@@ -715,7 +720,6 @@ def test_domain_audits_use_business_object_names():
assert "_equipment_audit_detail" in sources["material_equipments.py"]
assert "_visit_audit_detail" in sources["visits.py"]
assert "_ae_audit_detail" in sources["aes.py"]
assert "_precaution_audit_detail" in sources["precautions.py"]
assert "_contract_audit_detail" in sources["fees_contracts.py"]
assert "_payment_audit_detail" in sources["fees_contracts.py"]
assert "_feasibility_audit_detail" in sources["startup.py"]
+19 -27
View File
@@ -140,7 +140,6 @@ async def test_copy_revision_saves_to_the_selected_workspace_folder(monkeypatch,
content=content,
source="COPY",
user=user,
source_file_id=item.id,
)
@@ -159,22 +158,13 @@ async def test_delete_revision_soft_deletes_a_non_current_version(monkeypatch):
)
db = SimpleNamespace(get=AsyncMock(return_value=revision), commit=AsyncMock())
require_manager = AsyncMock()
audit = AsyncMock()
monkeypatch.setattr(collaboration_service, "require_file_manager", require_manager)
monkeypatch.setattr(collaboration_service, "_audit", audit)
await collaboration_service.delete_revision(db, item, revision_id, user)
require_manager.assert_awaited_once_with(db, item, user)
assert revision.deleted_at is not None
assert revision.deleted_by == user.id
audit.assert_awaited_once_with(
db,
item,
"COLLABORATION_REVISION_DELETED",
user,
{"revision_id": str(revision_id), "revision_no": 2},
)
db.commit.assert_awaited_once()
@@ -260,7 +250,6 @@ async def test_sheet_permission_change_updates_current_file_without_creating_rev
user = SimpleNamespace(id=uuid.uuid4())
db = SimpleNamespace(get=AsyncMock(return_value=revision), commit=AsyncMock(), refresh=AsyncMock())
monkeypatch.setattr(collaboration_service, "require_file_manager", AsyncMock())
monkeypatch.setattr(collaboration_service, "_audit", AsyncMock())
persist_revision = AsyncMock()
monkeypatch.setattr(collaboration_service, "_persist_revision_bytes", persist_revision)
@@ -540,7 +529,6 @@ async def test_share_link_url_stays_immutable_when_disabled_and_reenabled(monkey
refresh=AsyncMock(),
)
monkeypatch.setattr(collaboration_service, "require_file_manager", AsyncMock())
monkeypatch.setattr(collaboration_service, "_audit", AsyncMock())
original_token = collaboration_share_service.share_token(link)
await collaboration_share_service.update_share_link(
@@ -803,12 +791,11 @@ async def test_copy_creates_an_independent_r1_from_the_current_revision(monkeypa
content=content,
source="COPY",
user=user,
source_file_id=item.id,
)
@pytest.mark.asyncio
async def test_download_returns_current_revision_and_records_audit(monkeypatch, tmp_path):
async def test_download_returns_current_revision_without_writing_audit(monkeypatch, tmp_path):
source = tmp_path / "source.docx"
source.write_bytes(collaboration_service.blank_file_bytes("word"))
revision = SimpleNamespace(
@@ -821,22 +808,33 @@ async def test_download_returns_current_revision_and_records_audit(monkeypatch,
user = SimpleNamespace(id=uuid.uuid4())
db = SimpleNamespace(get=AsyncMock(return_value=revision), commit=AsyncMock())
require_exporter = AsyncMock()
audit = AsyncMock()
monkeypatch.setattr(collaboration_service, "require_file_exporter", require_exporter)
monkeypatch.setattr(collaboration_service, "_audit", audit)
result = await collaboration_service.prepare_download(db, item, user)
assert result is revision
require_exporter.assert_awaited_once_with(db, item, user)
audit.assert_awaited_once_with(
db.commit.assert_not_awaited()
@pytest.mark.asyncio
async def test_revision_preview_does_not_write_passive_audit(monkeypatch, tmp_path):
revision_path = tmp_path / "revision.docx"
revision_path.write_bytes(b"office")
revision = SimpleNamespace(id=uuid.uuid4(), file_uri=str(revision_path), revision_no=2)
item = SimpleNamespace(id=uuid.uuid4())
db = SimpleNamespace(commit=AsyncMock())
monkeypatch.setattr(collaboration_service, "get_revision_or_404", AsyncMock(return_value=revision))
result = await collaboration_service.prepare_revision_preview(
db,
item,
"COLLABORATION_FILE_DOWNLOADED",
user,
{"revision_id": str(revision.id), "revision_no": 3},
revision.id,
SimpleNamespace(id=uuid.uuid4()),
)
db.commit.assert_awaited_once()
assert result is revision
db.commit.assert_not_awaited()
@pytest.mark.asyncio
@@ -1041,12 +1039,6 @@ async def test_force_save_updates_session_recovery_revision(monkeypatch):
"append_revision",
AsyncMock(return_value=(revision, True)),
)
monkeypatch.setattr(
onlyoffice_collaboration_service.collaboration_service,
"_audit",
AsyncMock(),
)
result = await onlyoffice_collaboration_service.process_callback(
db,
session.id,
@@ -128,7 +128,6 @@ async def test_edit_request_notifies_the_active_file_owner_and_managers(monkeypa
"get_member",
AsyncMock(return_value=SimpleNamespace(is_active=True)),
)
monkeypatch.setattr(collaboration_service, "_audit", AsyncMock())
monkeypatch.setattr(collaboration_service.notification_service, "create_recipient_notifications", notify)
result = await collaboration_service.create_edit_request(db, item, user)
-4
View File
@@ -39,12 +39,10 @@ async def test_attachment_config_reuses_permission_and_preserves_original_name(m
content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
)
permission = AsyncMock()
audit = AsyncMock()
monkeypatch.setattr(onlyoffice_api.attachment_crud, "get_attachment", AsyncMock(return_value=attachment))
monkeypatch.setattr(onlyoffice_api, "_ensure_study_exists", AsyncMock())
monkeypatch.setattr(onlyoffice_api, "_ensure_attachment_permission", permission)
monkeypatch.setattr(onlyoffice_api.onlyoffice_service, "ensure_onlyoffice_available", AsyncMock())
monkeypatch.setattr(onlyoffice_api, "_log_preview_open", audit)
response = Response()
db = object()
@@ -54,7 +52,6 @@ async def test_attachment_config_reuses_permission_and_preserves_original_name(m
assert result.file_name == "研究方案最终版.DOCX"
assert result.config["document"]["title"] == "研究方案最终版.DOCX"
assert response.headers["Cache-Control"] == "no-store"
audit.assert_awaited_once()
@pytest.mark.asyncio
@@ -96,7 +93,6 @@ async def test_version_config_reuses_document_access_and_version_hash(monkeypatc
monkeypatch.setattr(onlyoffice_api.document_crud, "get", AsyncMock(return_value=document))
monkeypatch.setattr(onlyoffice_api.document_service, "_ensure_study_access", access)
monkeypatch.setattr(onlyoffice_api.onlyoffice_service, "ensure_onlyoffice_available", AsyncMock())
monkeypatch.setattr(onlyoffice_api, "_log_preview_open", AsyncMock())
result = await onlyoffice_api.get_version_preview_config(version.id, Response(), object(), user)