Files
live-hub-py/web/backend/permissions.py
T
yml2213 df8c63b829 feat(huya): 外部 CK 协作台账(S1–S6)+ 图片上传能力
协作台账:新表 huya_external_orders 替代 Excel 多人协同表(设计见
docs/设计-虎牙外部CK协作台账.md),一条 CK 一行,所有人共享、改动留痕。

- 前端 pages/HuyaCollabPage.tsx + 菜单「虎牙 → 外部单协作」/huya/collab:
  内联编辑(带乐观锁 version)、图片缩略图、详情抽屉(字段表单 + 两个图片槽位 +
  操作时间线)、粘贴导入弹窗(带 TSV 预览)、批量/单条验证 CK、页头统计条、筛选
- 两套状态机:业务 pending→bound→recharged→scripted→done(旁路 void)、
  凭据 unverified/valid/invalid/disabled;唯一写入口在 services/huya_collab_service.py,
  字段级审计 + 整数 version 乐观锁(不用 updated_at:DATETIME 只到秒)
- CK 只读探针 check_user_bind_game_account(真机判据:响应非 None 且 status == 200),
  成功即覆盖写绑定快照 bind_game_account/bind_game_role/bind_game_channel(迁移 0056),
  失败只改凭据状态、不动业务状态;人工只能停用/恢复(POST /{id}/ck/status)
- 贴/换/重建 CK、TSV 批量导入(SAVEPOINT 单行隔离,部分失败不整体失败)、
  权限 huya:collab:view/edit/manage(删除只给运营)
- 孤儿图清理脚本 scripts/cleanup_orphan_file_assets.py(默认 --dry-run)

图片上传(协作台账截图用):OSS/本地双后端 + 缩略图变体 + /api/files 代理回读,
权限 file:upload / file:view。

验证:pytest 880 passed / 6 skipped;ruff format 全绿、ruff check 仅剩既有告警;
前端 tsc -b / eslint / vite build 通过;接口端到端冒烟 29 项全绿(TestClient,探针用假客户端);
探针真机冒烟 3 例(有效 CK=True、别人 uid=False、裸 cookie=False)。
2026-10-16 19:38:59 +08:00

170 lines
5.6 KiB
Python

"""权限点定义与角色默认权限"""
# ---- 权限点 ----
PERMISSIONS = {
# 用户管理
"user:view": "查看用户列表",
"user:create": "创建用户",
"user:edit": "编辑用户",
"user:rename": "修改用户名",
"user:delete": "删除用户",
"user:assign_permissions": "分配权限",
# 账号管理
"account:view_all": "查看所有账号(仅用户名、标签、分配)",
"account:view_full": "查看账号完整字段(密码/邮箱,仅管理员)",
"account:view_assigned": "查看分配给自己的账号",
"account:import": "导入账号",
"account:tag": "修改账号标签",
"account:remark": "修改账号备注",
"account:check": "账号检测",
"account:assign": "分配账号给客服",
"account:delete": "删除账号",
"account:manage": "停用/归档账号、开关自动化",
# 登录任务
"login:batch": "发起批量登录",
"login:view_all": "查看所有登录任务",
"login:view_assigned": "查看自己账号的登录任务",
# Cookie
"cookie:view": "查看 Cookie",
"cookie:operate": "检测/重登已分配账号 Cookie(不含查看)",
"cookie:export": "导出 Cookie",
# 斗鱼活动
"douyu:task": "斗鱼任务管理",
"douyu:config": "斗鱼配置管理",
"yyb:session": "应用宝扫码登录与角色查询",
"yyb:recharge": "应用宝充值与付款",
"yyb:manage": "接管并操作他人的应用宝任务",
"yyb:history": "查看应用宝充值历史",
# 虎牙
"huya:account": "虎牙账号管理(兼容旧权限)",
"huya:view_all": "查看所有虎牙账号",
"huya:view_assigned": "查看分配给自己的虎牙账号",
"huya:import": "导入/登录虎牙账号",
"huya:tag": "修改虎牙账号标签",
"huya:assign": "分配虎牙账号",
"huya:delete": "删除虎牙账号",
"huya:cookie:view": "查看虎牙 Cookie",
"huya:cookie:export": "导出/清除虎牙 Cookie",
"huya:task": "虎牙任务管理",
"huya:bind": "虎牙绑定操作",
"huya:recharge": "虎牙充值操作",
"huya:config": "虎牙配置管理",
# 外部 CK 协作台账(共享表,替代 Excel;见 docs/设计-虎牙外部CK协作台账.md)
"huya:collab:view": "查看外部 CK 协作台账",
"huya:collab:edit": "编辑外部 CK 协作台账",
"huya:collab:manage": "删除外部 CK 协作台账",
# 代理 & 白名单
"proxy:manage": "代理配置管理",
"whitelist:manage": "白名单配置管理",
"whitelist:test": "测试白名单",
# 自动化
"automation:view": "查看自动化作业与运行历史",
"automation:manage": "修改自动化配置、手动触发作业",
# 文件/附件(在线协作上传图片)
"file:view": "查看上传的文件",
"file:upload": "上传文件",
# 系统
"system:settings": "系统设置",
"audit:view": "查看审计日志",
}
# ---- 角色默认权限 ----
ROLE_PERMISSIONS = {
"super_admin": list(PERMISSIONS.keys()), # 全部权限
"operation": [
"account:view_all",
"account:import",
"account:tag",
"account:remark",
"account:check",
"account:assign",
"account:manage",
"login:batch",
"login:view_all",
"cookie:view",
"cookie:export",
"douyu:task",
"douyu:config",
"yyb:session",
"yyb:recharge",
"yyb:manage",
"yyb:history",
"huya:account",
"huya:view_all",
"huya:import",
"huya:tag",
"huya:assign",
"huya:delete",
"huya:cookie:view",
"huya:cookie:export",
"huya:task",
"huya:bind",
"huya:recharge",
"huya:config",
# 协作台账是共享表:运营既能改也能删。
"huya:collab:view",
"huya:collab:edit",
"huya:collab:manage",
"proxy:manage",
"whitelist:manage",
"whitelist:test",
"automation:view",
"file:view",
"file:upload",
],
"support": [
"account:view_assigned",
"account:tag",
"account:remark",
"douyu:task",
"yyb:session",
"yyb:history",
"huya:view_assigned",
"huya:tag",
"huya:task",
# 客服能看能改(共享表,靠审计留痕),但删除只给运营。
"huya:collab:view",
"huya:collab:edit",
"file:view",
"file:upload",
],
}
# 角色中文映射
ROLE_LABELS = {
"super_admin": "超级管理员",
"operation": "运营",
"support": "客服",
}
def get_role_permissions(role: str) -> list[str]:
"""获取角色拥有的权限列表。"""
return ROLE_PERMISSIONS.get(role, [])
def get_user_permissions(user) -> list[str]:
"""获取用户的实际权限列表。
优先使用用户自定义权限(custom_permissions),
若为 None 则回退到角色默认权限。
"""
if user.custom_permissions is not None:
return user.custom_permissions
return get_role_permissions(user.role)
def has_permission(role: str, permission: str) -> bool:
"""检查角色是否拥有某权限(仅检查角色默认权限,不考虑自定义权限)。
注意:对于需要考虑用户自定义权限的场景,请使用 user_has_permission()。
"""
return permission in get_role_permissions(role)
def user_has_permission(user, permission: str) -> bool:
"""检查用户是否拥有某权限(考虑自定义权限)。
优先使用用户的 custom_permissions,若为 None 则回退到角色默认权限。
"""
return permission in get_user_permissions(user)