Skip to content

feat(channels): 飞书渠道协作者管理与启停 - #193

Merged
fadeoreo merged 3 commits into
OpenBMB:mainfrom
skywclouds:feat/feishu-binding-collaborators
Aug 19, 2026
Merged

feat(channels): 飞书渠道协作者管理与启停#193
fadeoreo merged 3 commits into
OpenBMB:mainfrom
skywclouds:feat/feishu-binding-collaborators

Conversation

@skywclouds

Copy link
Copy Markdown
Contributor

意图

解决飞书渠道绑定「仅创建者一人能管理」的限制:允许创建者显式添加协作者,协作者可配置/轮换凭证、管理挂载员工、启停渠道,但不能删除渠道或管理其他协作者。

改动

后端

  • 新增 ChannelBindingManager 表(软撤销 revoked_at + 审计字段;create_all 自动建表,无需迁移)
  • _ensure_binding_manager 改为按 action 粒度校验(manage_credentials / manage_agents / toggle_status 放行协作者)
  • list_channel_bindings 放开协作者可见性,并在 ChannelBindingRead 上返回 my_role(admin/owner/collaborator)
  • 新增 GET/POST/DELETE /{binding_id}/managers 协作者管理端点(加/移/列;移除走软撤销,重新添加复活该行)
  • 新增 POST /{binding_id}/toggle-status 启停渠道端点(停用 quiesce 长连接,启用按需 resume,复用凭证保存/删除同款生命周期管理)

前端

  • 渠道详情新增角色徽标、启停按钮、协作者管理面板
  • 断开接入按钮按 my_role 显隐(仅 owner/admin)
  • 新增 BindingManagers.tsx 组件(复用 tenantUsers 做成员选择,排除创建者/管理员/已有协作者)
  • 权限纯函数提取到 channelPresentation.tscanDeleteBinding / canManageBinding / ROLE_LABEL

权限边界

操作 admin 创建者 协作者 其他成员
配置/轮换凭证
管理挂载员工
启停渠道
删除渠道
管理协作者名单
查看投递/会话记录

风险

  • 启停渠道为补齐的缺失功能(之前无独立端点,状态切换仅发生在凭证保存路径);停用走 quiesce 断长连接 + status=disabled,启用 status=active + 有凭证时 resume,与既有删除/凭证保存同款 quiesce/resume 范式。
  • 凭证安全ChannelBindingRead 注释明确「绝不回传凭证明文」,app_secret 不在读取视图;协作者只能重填/轮换,无法查看明文。
  • 协作者变更走软撤销(revoked_at)保留 who/when 审计;同一 (binding, user) 仅一行,重新添加复活而非新增。
  • 投递日志/会话记录等只读查看端点维持原行为(仅创建者+admin),协作者暂不可见,如需放开可后续加 view action。

测试

  • 后端:新增 test_channel_managers.py(11 个用例:协作者能配凭证/管挂载/启停、不能删除/不能管协作者、非协作者 403、列表可见性与 my_role、软撤销后失去权限再添加恢复、添加校验 400/409、admin 可管协作者);既有 channel 套件 455 passed,零破坏。
  • 前端tsc + vite build 通过;vitest 186 passed(新增 11 个 channelPresentation 权限函数用例)。
  • config:check 通过;i18n:check exit 1 为既有状态(改动前即失败),跟随既有中文硬编码风格。

UI 验证

  • 路由:/enterprise/channels → 飞书渠道详情
  • 角色:创建者、协作者、管理员分别验证「断开接入 / 启停 / 协作者管理面板」的显隐与可用性

- 新增 ChannelBindingManager 表与协作者管理 API(GET/POST/DELETE managers)

- _ensure_binding_manager 改为按操作粒度:协作者可凭证/挂载/启停,删除与管理协作者仅创建者+admin

- list_channel_bindings 放开协作者可见性并返回 my_role

- 新增 POST /{binding_id}/toggle-status 启停渠道端点

- 前端:角色徽标、断开接入按角色显隐、启停按钮、协作者管理面板
@fadeoreo

Copy link
Copy Markdown
Collaborator

[P1] OIDC 登录入口忽略 VITE_API_BASE_URL,分离部署时无法发起登录
[frontend-enterprise/src/pages/LoginPage.tsx (line 70)](/Users/a1/Documents/openbmb 新项目/StaffDeck/frontend-enterprise/src/pages/LoginPage.tsx:70) 使用了硬编码的相对路径 '/api/auth/oidc/authorize'。但前端其他请求都通过 api 客户端拼接 VITE_API_BASE_URL。当控制台和 FastAPI 部署在不同 origin 时,点击 SSO 会请求前端域名下的 /api/auth/oidc/authorize,而不是 API 服务,通常会得到 404 或前端 fallback 页面。后端回调成功后还固定重定向到 /login,也会落到 API origin,进一步使分离部署无法完成登录。建议统一使用 API base URL,并配置/返回明确的前端登录落点,或让后端根据部署配置生成完整 landing URL。

@skywclouds

Copy link
Copy Markdown
Contributor Author

感谢 @fadeoreo 的反馈。经核实,当前仓库(OpenBMB/StaffDeck main 及本 PR 的 fork base)并不存在 OIDC 登录入口代码,因此无法直接「修改」该硬编码:

  • 全库 git grep -iE "oidc|sso|saml|authorize" 仅在 README.md / README.zh.md / QuickStartGuide.tsx 命中文档与提示,无任何 authorize/callback 实现;
  • frontend-enterprise/src/pages/LoginPage.tsx 全文搜索 oidc|authorize|sso 无输出,第 70 行实际为 <main> 标签,并非 /api/auth/oidc/authorize
  • 后端 backend/app/apibackend/app/security 也无 OIDC authorize/callback 端点;
  • 普通登录 api.post('/api/auth/login') 已通过 api 客户端拼接 VITE_API_BASE_URLfrontend-enterprise/src/api/client.ts${API_BASE}${path}),并未硬编码相对路径。

评论引用的路径 /Users/a1/Documents/openbmb 新项目/StaffDeck/... 似乎基于本地未推送的 WIP 版本,GitHub 仓库当前并无该段代码。

这一点确实会在分离部署时让 SSO 跳到前端 origin。待 OIDC SSO 功能正式合入仓库后,会按此建议落地:前端 SSO 入口统一用 ${API_BASE}/api/auth/oidc/authorize,后端回调根据部署配置生成完整 landing URL(而非固定 /login)。本 PR(飞书渠道协作者管理)不涉及 OIDC,故不在此次改动范围内。

如需要,我可以在单独的 PR 中直接新增 OIDC SSO 入口实现并按上述原则处理 base URL 与 landing URL。

@fadeoreo fadeoreo self-assigned this Aug 19, 2026
@fadeoreo
fadeoreo merged commit d65da40 into OpenBMB:main Aug 19, 2026
4 checks passed
@skywclouds
skywclouds deleted the feat/feishu-binding-collaborators branch August 20, 2026 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants