2026-05-18 09:45:05 +00:00
|
|
|
from io import BytesIO
|
2026-07-17 14:14:08 +08:00
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
|
|
2026-05-18 09:45:05 +00:00
|
|
|
from openpyxl import Workbook
|
2026-07-17 14:14:08 +08:00
|
|
|
|
|
|
|
|
from app.services.agent_asset_onlyoffice_security import (
|
|
|
|
|
AgentAssetOnlyOfficeValidatedSession,
|
|
|
|
|
)
|
2026-05-18 09:45:05 +00:00
|
|
|
from app.services.agent_assets import AgentAssetService
|
|
|
|
|
|
2026-07-17 14:14:08 +08:00
|
|
|
|
|
|
|
|
def test_onlyoffice_callback_delegates_downloaded_workbook_to_upload():
|
2026-05-18 09:45:05 +00:00
|
|
|
db = MagicMock()
|
|
|
|
|
service = AgentAssetService(db)
|
|
|
|
|
service._ensure_ready = MagicMock()
|
2026-07-17 14:14:08 +08:00
|
|
|
|
2026-05-18 09:45:05 +00:00
|
|
|
asset = MagicMock()
|
|
|
|
|
asset.id = "test-asset"
|
2026-07-17 14:14:08 +08:00
|
|
|
asset.tenant_id = "tenant-a"
|
|
|
|
|
asset.scope = "tenant"
|
2026-05-18 09:45:05 +00:00
|
|
|
service._require_spreadsheet_rule = MagicMock(return_value=asset)
|
2026-07-17 14:14:08 +08:00
|
|
|
current_metadata = MagicMock(file_name="test.xlsx", checksum="old-checksum")
|
|
|
|
|
service._resolve_current_spreadsheet_meta = MagicMock(
|
|
|
|
|
return_value=("current", current_metadata)
|
|
|
|
|
)
|
|
|
|
|
|
2026-05-18 09:45:05 +00:00
|
|
|
new_wb = Workbook()
|
|
|
|
|
new_ws = new_wb.active
|
2026-07-17 14:14:08 +08:00
|
|
|
new_ws["A1"] = "new value"
|
|
|
|
|
new_ws["B2"] = "added"
|
2026-05-18 09:45:05 +00:00
|
|
|
new_content_bio = BytesIO()
|
|
|
|
|
new_wb.save(new_content_bio)
|
|
|
|
|
new_content = new_content_bio.getvalue()
|
2026-07-17 14:14:08 +08:00
|
|
|
document_key = service._build_onlyoffice_document_key("test-asset", current_metadata)
|
|
|
|
|
claimed = AgentAssetOnlyOfficeValidatedSession(
|
|
|
|
|
jti="callback-jti",
|
|
|
|
|
tenant_id="tenant-a",
|
|
|
|
|
resource_scope="tenant",
|
|
|
|
|
asset_id="test-asset",
|
|
|
|
|
document_key=document_key,
|
|
|
|
|
document_version="current",
|
|
|
|
|
document_fingerprint="old-checksum",
|
|
|
|
|
writable=True,
|
|
|
|
|
actor="username:test_user",
|
|
|
|
|
status="processing",
|
|
|
|
|
)
|
|
|
|
|
session_service = MagicMock()
|
|
|
|
|
session_service.claim_callback.return_value = claimed
|
|
|
|
|
service._onlyoffice_session_service = MagicMock(return_value=session_service)
|
|
|
|
|
|
|
|
|
|
with patch(
|
|
|
|
|
"app.services.agent_asset_onlyoffice.download_onlyoffice_document",
|
|
|
|
|
return_value=new_content,
|
|
|
|
|
) as secure_download:
|
2026-05-18 09:45:05 +00:00
|
|
|
service.upload_rule_spreadsheet = MagicMock()
|
|
|
|
|
payload = {
|
|
|
|
|
"status": 2,
|
|
|
|
|
"url": "http://onlyoffice/download",
|
2026-07-17 14:14:08 +08:00
|
|
|
"key": document_key,
|
2026-05-18 09:45:05 +00:00
|
|
|
}
|
2026-07-17 14:14:08 +08:00
|
|
|
|
2026-05-18 09:45:05 +00:00
|
|
|
service.handle_rule_spreadsheet_onlyoffice_callback(
|
|
|
|
|
"test-asset",
|
2026-07-17 14:14:08 +08:00
|
|
|
version="current",
|
|
|
|
|
payload=payload,
|
|
|
|
|
callback_token="signed-callback-token",
|
2026-05-18 09:45:05 +00:00
|
|
|
)
|
|
|
|
|
|
2026-07-17 14:14:08 +08:00
|
|
|
secure_download.assert_called_once_with(
|
|
|
|
|
"http://onlyoffice/download",
|
|
|
|
|
expected_filename="test.xlsx",
|
|
|
|
|
)
|
|
|
|
|
service.upload_rule_spreadsheet.assert_called_once_with(
|
|
|
|
|
"test-asset",
|
|
|
|
|
filename="test.xlsx",
|
|
|
|
|
content=new_content,
|
|
|
|
|
actor="username:test_user",
|
|
|
|
|
source="onlyoffice",
|
|
|
|
|
)
|
|
|
|
|
session_service.finish_callback.assert_called_once_with(
|
|
|
|
|
"callback-jti",
|
|
|
|
|
succeeded=True,
|
|
|
|
|
)
|