"""充值审计日志的权限、查询和脱敏测试。""" import pytest import json from fastapi import HTTPException from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from web.backend.database import Base from web.backend.models import Account, AuditLog, DouyuTask, User from web.backend.routers.audit import list_audit_logs, require_super_admin from web.backend.services.audit_service import record_audit class TestAuditLog: def setup_method(self): self.engine = create_engine("sqlite://") Base.metadata.create_all(self.engine) self.session = sessionmaker(bind=self.engine)() self.admin = User(username="admin", password_hash="hash", role="super_admin") self.operator = User( username="operator", password_hash="hash", role="operation", custom_permissions=["audit:view"], ) self.session.add_all([self.admin, self.operator]) self.session.commit() def teardown_method(self): self.session.close() Base.metadata.drop_all(self.engine) self.engine.dispose() def test_only_super_admin_can_read_audit_logs(self): with pytest.raises(HTTPException) as context: require_super_admin(self.operator) assert context.value.status_code == 403 assert require_super_admin(self.admin) is self.admin def test_list_audit_logs_supports_pagination_and_result_filter(self): for index in range(3): record_audit( self.session, self.admin, action="recharge:yyb:payment", target=f"yyb_task:{index}", detail={"task_id": index}, success=index != 1, ) self.session.commit() result = list_audit_logs( page=1, page_size=1, username=None, action="recharge:yyb:payment", keyword=None, success=True, start_time=None, end_time=None, db=self.session, _=self.admin, ) assert result["total"] == 2 assert len(result["items"]) == 1 assert result["items"][0]["success"] def test_audit_detail_masks_sensitive_fields(self): record_audit( self.session, self.admin, action="recharge:yyb:payment", detail={ "token": "token-value", "nested": {"cookie": "cookie-value"}, "order_id": "order-1", }, ) self.session.commit() entry = self.session.query(AuditLog).one() detail = json.loads(entry.detail) assert detail["token"] == "[已脱敏]" assert detail["nested"]["cookie"] == "[已脱敏]" assert detail["order_id"] == "order-1" def test_old_douyu_recharge_log_is_enriched_with_account_identity(self): account = Account( username="douyu-login", password="password", email="mail@example.com", email_password="mail-password", uid="10001", nickname="斗鱼昵称", ) self.session.add(account) self.session.commit() self.session.add( DouyuTask( batch_id="batch-old", account_id=account.id, task_type="create_gold_qr", handbook_scope="elite", created_by=self.admin.id, ) ) self.session.add( AuditLog( user_id=self.admin.id, username=self.admin.username, action="recharge:douyu:create", target="douyu_batch:batch-old", detail="{}", success=True, ) ) self.session.commit() result = list_audit_logs( page=1, page_size=50, username=None, action=None, keyword=None, success=None, start_time=None, end_time=None, db=self.session, _=self.admin, ) detail = json.loads(result["items"][0]["detail"]) assert detail["recharge_accounts"][0]["username"] == "douyu-login" assert detail["recharge_accounts"][0]["douyu_uid"] == "10001" assert detail["recharge_channel"] == "wechat_qr" assert detail["payment_method"] == "微信扫码支付"