"""当前用途与历史内容独立;重导入不会复活撤权。""" from dataclasses import replace from types import SimpleNamespace import pytest from muse.资料研究 import 来源导入, 来源授权 from muse.资料研究.接口 import 资料服务 from muse.资料研究.来源授权 import 授权写入, 来源用途变更 from muse.资料研究.模型 import 导入请求, 资料错误 源ID = "12345678-1234-1234-1234-123456789abc" @pytest.fixture def 授权环境(monkeypatch): 状态 = {"authorized_uses": ["analysis", "sample"], "authorization_revision": 1} 更新 = [] monkeypatch.setattr(来源授权, "读取当前授权", lambda *a: dict(状态)) class 存储: def __init__(self, 连): pass def 查询(self, sql, params): uses, source_id, revision = params assert source_id == 源ID and revision == 状态["authorization_revision"] 更新.append(tuple(uses.obj)) 状态.update(authorized_uses=uses.obj, authorization_revision=revision + 1) return SimpleNamespace(fetchone=lambda: dict(状态)) monkeypatch.setattr(来源授权, "资料存储", 存储) return 状态, 更新 @pytest.mark.case_id("NC-O09-REVOKE") def test_用途可减少或清空且不变请求不升版(授权环境): 状态, 更新 = 授权环境 请求 = 来源用途变更(源ID, 1, ("analysis",), "撤回样本") 提交 = 来源授权.来源授权参与者().提交 assert 提交(None, 授权写入("author", 请求))["authorization_revision"] == 2 assert 状态["authorized_uses"] == ["analysis"] 同值 = replace(请求, expected_authorization_revision=2) assert 提交(None, 授权写入("author", 同值))["no_change"] with pytest.raises(资料错误, match="版本已改变"): 提交(None, 授权写入("author", 请求)) 全撤 = replace(同值, uses=(), reason="撤回全部") assert 提交(None, 授权写入("author", 全撤))["authorization_revision"] == 3 assert 更新 == [("analysis",), ()] @pytest.mark.case_id("NC-O09-REIMPORT") def test_旧导入请求不复活授权(monkeypatch): calls = [] class 存储: def __init__(self, 连): pass def 锁来源导入(self, *a): calls.append("lock-origin") def 查源(self, *a): return {"source_id": 源ID, "authorized_uses": ["analysis"]} def 锁当前来源版本(self, *a): calls.append("lock-source") def 建源(self, *a): pytest.fail("已有来源重导入不得写授权") def 写版本(self, *a): pytest.fail("冲突请求不得写版本") monkeypatch.setattr(来源导入, "资料存储", 存储) with pytest.raises(资料错误, match="重导入不能修改"): 来源导入.导入来源( None, "author", 导入请求("reference", "样例", "fixture://source", "合成文字", ("analysis", "sample")), ) assert calls == ["lock-origin", "lock-source"] @pytest.mark.case_id("NC-O09-SAMPLE") def test_撤回sample保留analysis只返回定位哈希(monkeypatch): import muse.资料研究.接口 as 接口 服务 = 资料服务() def 核对(连, source, purpose): if purpose == "sample": raise 资料错误("撤回sample") return {"authorized_uses": ["analysis"], "authorization_revision": 2} monkeypatch.setattr(服务, "核对来源授权", 核对) monkeypatch.setattr( 服务, "读取版本", lambda *a, **k: { "import_result": {"导入者": "author"}, "content": "合成文字", "content_hash": "hash", }, ) monkeypatch.setattr(服务, "读取当前版本号", lambda *a: 1) monkeypatch.setattr(接口, "读取证据", lambda *a: {"片段": "合成"}) 结果 = 服务.读取案例证据(None, "author", 源ID, 1, 0, 2) assert 结果["excerpt"] is None and 结果["context"] is None and not 结果["text_allowed"] assert 结果["excerpt_hash"] and 结果["current_revision"] == 1 @pytest.mark.case_id("NC-O09-HTTP-AUTH") def test_HTTP授权动作调用同一具名服务(): from unittest.mock import patch import muse.接入.http.路由.资料研究 as 模块 from muse.接入.http.路由.资料研究 import 变更来源用途, 来源授权请求 calls = [] 服务 = SimpleNamespace( 变更来源用途=lambda *args: calls.append(args) or {"receipt_id": "receipt"} ) 装配 = SimpleNamespace(配置=None, 要求资料=lambda: 服务) request = SimpleNamespace(app=SimpleNamespace(state=SimpleNamespace(装配=装配))) with patch.object(模块, "创作身份", lambda *a: "identity"): result = 变更来源用途( 源ID, 来源授权请求( command_id="revoke", expected_authorization_revision=2, uses=[], reason="撤回" ), request, "author", ) assert result == {"receipt_id": "receipt"} assert calls == [("identity", "revoke", 来源用途变更(源ID, 2, (), "撤回"))]