Lingchu Bot 文档现已上线 — 快来看看吧!
Lingchu Bot

权限系统

UID 超级用户、身份组、命令授权与受保护目标拦截。

权限系统

Lingchu Bot 采用分层权限系统,融合 Lingchu 全局 UID 身份、平台账号绑定、身份组成员关系,以及按命令的 allow-list 授权。本页描述运行时如何解析权限、超级用户如何配置,以及黑名单和受保护目标策略如何对破坏性命令设防。

架构分层

文件职责
启动引导permissions/bootstrap.py校验 LINGCHU_SUPERUSERS、种子默认身份组、启动时同步超级用户成员关系与命令授权
服务permissions/service.py解析 PermissionContext、执行 check_permission、展开运行时与成员组、查询授权
管理 APIpermissions/admin.py仅超级用户可调用:创建/更新/删除身份组、添加/移除成员
目标策略permissions/subject_policy.py黑名单与受保护目标条目,带过期的活跃策略查询
平台集成permissions/platforms.py通过 PlatformProfile.permission_module 发现平台权限模块,解析运行时身份组
仓库repositories/permissions.pyIdentityUserPlatformAccountPlatformIdentityGroupIdentityMembershipPermissionGrant 的 ORM CRUD

UID 超级用户与平台账号映射

超级用户通过 LINGCHU_SUPERUSERS 环境键(NoneBot 配置别名 lingchu_superusers)声明。值是从 Lingchu UID 到一个或多个平台账号绑定的 JSON 映射:

{
  "alice": { "qq": 10001 },
  "bob": { "qq": 10002 }
}

启动时,permissions/bootstrap.py 中的 validate_and_seed_permission_system() 会:

  1. runtime_config.lingchu_superusers 读取配置映射。
  2. 将每个 UID 和平台账号 ID 规范化为字符串(QQ 账号校验为正整数)。
  3. 校验每个 platform_id 是否为已知平台 profile,且每个 (platform_id, account_id) 对未被重复绑定。
  4. 将每个 UID upsert 到 IdentityUser,添加到 system.superusers 组(source 为 superusers_config),并通过 bind_platform_account() 绑定每个平台账号。
  5. 将所有 MENU_FEATURES.command_key 授权给 system.superusers 组,使超级用户可执行所有命令。

如果 LINGCHU_SUPERUSERS 缺失或为空,启动会抛出 PermissionConfigError 并中止。

命令授权与 MENU_FEATURES.command_key

每个命令由 handle/menu.pyMenuFeature 上声明的稳定 command_key 标识。同一个 command_key 是以下场景的共享标识:

  • 权限检查(check_permission(command_key, bot, event)
  • 菜单过滤(allowed_command_keys() 隐藏当前身份无法执行的命令)
  • 处理器装饰器与触发词注册
  • lingchu_permission_grants 表中的权限授权

permissions/service.py 中的 check_permission_for_context() 按以下短路顺序解析 PermissionDecision

  1. context.uidNoneallowed=False, reason="anonymous"
  2. repo.is_superuser(uid)allowed=True, reason="superuser"
  3. 否则,从运行时透传(启用时)加上匹配的 IdentityMembership 行收集有效身份组,通过 parent_group_id 展开到祖先组,查询 effect == "allow"PermissionGrant 行。
  4. 若任意授权匹配 → allowed=True, reason="granted";否则 → allowed=False, reason="missing_grant"

平台运行时角色透传

permission_platform_runtime_passthrough 控制平台解析的运行时角色(例如 QQ 群主/管理员/成员)是否参与权限检查。它接受全局布尔值或按平台的映射:

permission_platform_runtime_passthrough = true
# 或按平台:
# permission_platform_runtime_passthrough = { qq = true }

当当前 platform_id 启用透传时,平台模块(见 permissions/platforms.py::resolve_runtime_identity_groups)返回的运行时身份组会被加入直接组集合,再进行授权查询。禁用时,仅显式 IdentityMembership 行生效。默认值为 True;按平台条目缺失时也回退到 True

permissions/service.py 中的 platform_runtime_passthrough_enabled()check_permission_for_context() 与菜单可见性路径共用的唯一解析器。

黑名单与受保护目标拦截

protected_subject_feature_keys 是必须先经过目标策略校验才能执行的 command_key 允许列表。默认覆盖破坏性操作:

protected_subject_feature_keys = [
  "kick_member",
  "block_member",
  "global_block_member",
  "member_mute",
  "recall_message",
  "set_member_card",
  "set_member_title",
  "set_member_admin",
  "unset_member_admin",
  "remote_kick",
  "remote_block",
  "remote_mute",
]

目标策略存储在 lingchu_subject_policy 表中,通过 permissions/subject_policy.py 暴露:

策略类型效果
blocked目标用户在黑名单中;受保护命令被拒绝
protected目标用户在保护名单中;针对其的破坏性命令被拒绝

find_active_subject_policy() 先查 global 作用域,再查 group 作用域,并惰性删除已过期条目。active_subject_policy_condition() 返回一个 SQLAlchemy 过滤器,排除 expires_at 已过期的行,供需要连接策略表的仓库查询使用。

权限种子与平台角色树

默认身份组从各平台权限模块种子而来。permissions/platforms.py::iter_default_identity_groups() 遍历每个 PlatformProfile.permission_module,并调用其 get_default_identity_groups()

对于 QQ,platforms/qq/permissions.py 声明 PLATFORM_ID = "qq" 并种子以下树:

组 ID父组显示名
qq.groupQQ群聊
qq.group.ownerqq.groupQQ群主
qq.group.adminqq.groupQQ群管理员
qq.group.memberqq.groupQQ群成员
qq.friendQQ好友
qq.channelQQ频道
qq.botQQ机器人
qq.deviceQQ设备

运行时,resolve_runtime_identity_groups() 将 OneBot V11 发送者角色(owner / admin / member)映射到对应 qq.group.* 组 ID。若事件中缺少角色,会回退到 bot.call_api("get_group_member_info", ...),API 失败时最终回退到 member 角色。

平台权限模块通过适配器注册表的 PlatformProfile.permission_module 字段动态发现——核心权限层中没有硬编码的模块路径。

权限数据模型

ORM 模型位于 database/models/identity.py,使用 database/_dialect_compat.py 中的跨方言兼容类型:

模型用途
lingchu_identity_usersIdentityUserLingchu 全局 UID,可选昵称
lingchu_platform_accountsPlatformAccountUID 与 (platform_id, account_id) 对的绑定
lingchu_platform_identity_groupsPlatformIdentityGroup平台作用域组,可选 parent_group_idbuiltin 标志
lingchu_identity_membershipsIdentityMembershipUID → 组成员关系,可按 scope_type / scope_id 限定作用域
lingchu_permission_grantsPermissionGrant从组到 command_key 的 allow-list 授权

SUPERUSERS_GROUP_ID = "system.superusers" 是唯一不按平台作用域的内置组;它由 bootstrap.py 而非平台模块种子。

管理 API

permissions/admin.py 暴露仅超级用户可调用的变更操作。每个函数首先调用 assert_superuser(),若执行者非超级用户则抛出 PermissionDeniedError

  • create_platform_identity_group() / update_platform_identity_group() / delete_platform_identity_group()
  • add_identity_group_member() / remove_identity_group_member() / list_identity_group_members()

内置组(builtin=True)无法更新或删除;仍有成员关系或授权的组无法删除。

参见

命令触发词与菜单可见性如何消费这些权限,参见架构概览适配器指南

最后更新于

本页目录