feat(huya): 协作台账勾选导出 CK 到剪贴板(单点权限 + 逐行审计)+ 工具区固定两行

This commit is contained in:
yml2213
2026-10-16 22:24:08 +08:00
parent 6ef74c8e45
commit 82c59bb4af
9 changed files with 431 additions and 6 deletions
+75
View File
@@ -1848,6 +1848,75 @@ class TestCollabActivityLifecycle(TestCollabBase):
assert payload["last_verdict"] == "success"
class TestCollabCkExport(TestCollabBase):
"""勾选导出 CK(写剪贴板):凭据外带要留痕,但审计里不许出现 CK 本体。"""
def test_export_returns_plaintext_and_audits_each_exported_row(self):
first = self._create(order_no="EXP-1", ck_text=fake_ck("1199647000001"))
second = self._create(order_no="EXP-2", ck_text=fake_ck("1199647000002"))
blank = self._create(order_no="EXP-3") # 没贴 CK
result = collab.export_cks(self.db, self.user, [first, second, blank])
assert result["total"] == 3
assert result["exported"] == 2
assert [item["order_no"] for item in result["items"]] == ["EXP-1", "EXP-2"]
# 明文就是库里的那一份(不是脱敏/预览;库里存的是**归一化后**的 CK,
# 所以跟 `fake_ck()` 的原始串不完全一样:重复的 guid 已被去掉)
assert result["items"][0]["ck_text"] == first.cookie
assert "udb_uid=1199647000001" in result["items"][0]["ck_text"]
assert result["items"][0]["ck_text"].count("guid=") == 1
assert result["items"][0]["uid"] == "1199647000001"
# 没 CK 的行显式跳过并回原因,不静默丢
assert [row["order_no"] for row in result["skipped"]] == ["EXP-3"]
assert "CK" in result["skipped"][0]["reason"]
def test_export_audit_never_contains_the_credential_body(self):
order = self._create(order_no="EXP-4", ck_text=fake_ck("1199647000004"))
collab.export_cks(self.db, self.user, [order])
audits = self._audits(order)
assert audits[-1].action == "huya:collab:ck_export"
assert audits[-1].username == self.user.username
assert order.order_no in audits[-1].detail # 只记「导出了哪一单」
# 凭据本体(udb_cred / udb_biztoken 那两段超长值)绝不能进审计
assert "udb_cred" not in audits[-1].detail
assert "C" * 152 not in audits[-1].detail
assert "T" * 200 not in audits[-1].detail
def test_export_skips_blank_rows_without_audit(self):
blank = self._create(order_no="EXP-5")
collab.export_cks(self.db, self.user, [blank])
assert [row.action for row in self._audits(blank)] == ["huya:collab:create"]
def test_export_keeps_void_and_disabled_rows_with_labels(self):
"""作废 / 停用的单只要还有 CK 就照导 —— 但状态标签要一起给,由人自己判断。"""
disabled = self._create(order_no="EXP-6", ck_text=fake_ck("1199647000006"))
collab.set_ck_status(
self.db, self.user, disabled, "disabled", message="不再使用"
)
voided = self._create(order_no="EXP-7", ck_text=fake_ck("1199647000007"))
collab.set_status(self.db, self.user, voided, "void", reason="客户退单")
result = collab.export_cks(self.db, self.user, [disabled, voided])
assert result["exported"] == 2
by_no = {item["order_no"]: item for item in result["items"]}
assert by_no["EXP-6"]["ck_status_label"] == "已停用"
assert by_no["EXP-7"]["status_label"] == "已作废"
assert by_no["EXP-7"]["status"] == "void"
def test_export_rejects_empty_and_too_many(self):
with pytest.raises(collab.CollabError) as excinfo:
collab.export_cks(self.db, self.user, [])
assert excinfo.value.code == "ck_export_empty"
with pytest.raises(collab.CollabError) as excinfo:
collab.export_cks(self.db, self.user, [None] * (collab.PROBE_BATCH_MAX + 1))
assert excinfo.value.code == "ck_export_too_large"
class TestProbeCache(TestCollabBase):
def test_same_ck_probed_twice_only_hits_the_api_once(self, monkeypatch):
calls: list[dict] = []
@@ -1902,6 +1971,12 @@ class TestCollabPermissions:
assert "file:view" in ROLE_PERMISSIONS[role]
assert "file:upload" in ROLE_PERMISSIONS[role]
def test_ck_export_is_operation_only_by_default(self):
"""导出 CK = 把凭据带出系统:默认只给运营(要发给客服就在权限页单独勾)。"""
assert "huya:collab:ck_export" in ROLE_PERMISSIONS["operation"]
assert "huya:collab:ck_export" not in ROLE_PERMISSIONS["support"]
assert "huya:collab:ck_export" in ROLE_PERMISSIONS["super_admin"]
def test_collab_module_does_not_touch_huya_accounts(self):
"""边界(设计文档 §2.3):本模块不建 HuyaAccount、不写工作台。"""
assert collab.HuyaExternalOrder.__tablename__ == "huya_external_orders"