feat: switch client API branding to MeetingIM
This commit is contained in:
+35
-34
@@ -29,7 +29,7 @@ API Key 是应用级接入标识,由部署人员在发布客户端前生成并
|
||||
|
||||
1. 新部署同时生成 API Key 和 HMAC Salt:在项目根目录执行 `go run ./keygen`。
|
||||
2. 已有服务端继续使用当前 `api_key_salt` 时,执行 `go run ./keygen -sequence <新序号> -salt '<服务端 api_key_salt>'` 生成兼容的普通应用 Key。
|
||||
3. 输出中的 `HMAC salt` 配置到服务端 `server/tinode.conf` 的 `api_key_salt`;输出中的 `API key` 配置到 iOS、Android 或 Web 客户端构建配置/受控环境配置。
|
||||
3. 输出中的 `HMAC salt` 配置到服务端 `server/meetingim.conf` 的 `api_key_salt`;输出中的 `API key` 配置到 iOS、Android 或 Web 客户端构建配置/受控环境配置。
|
||||
4. 客户端启动时从自己的应用配置读取 API Key,不调用 IM 接口获取。禁止把 `-isroot 1` 生成的 Root Key 放进客户端。
|
||||
|
||||
生成示意:
|
||||
@@ -44,7 +44,7 @@ API Key、企业码和用户 Token 是三个不同概念:
|
||||
|
||||
| 值 | 取得时间 | 作用 | 是否代表用户身份 |
|
||||
| --- | --- | --- | --- |
|
||||
| `api_key` | 应用发布/环境配置时预置 | 允许应用访问 Tinode 入口 | 否 |
|
||||
| `api_key` | 应用发布/环境配置时预置 | 允许应用访问 MeetingIM 入口 | 否 |
|
||||
| `tenant_code` | 用户输入企业码 | 将 Session 路由并绑定到企业 | 否 |
|
||||
| `token` | 用户登录成功后由服务端返回 | 标识当前租户内的登录用户 | 是 |
|
||||
|
||||
@@ -57,11 +57,11 @@ API Key 可以被客户端应用提取,因此不能把它当成用户密码或
|
||||
| 通道 | 地址 | 认证 | 用途 |
|
||||
| --- | --- | --- | --- |
|
||||
| WebSocket(浏览器/通用方式) | `wss://{host}/{api_path}v0/channels?apikey={api_key}` | Upgrade 校验 API Key,`hi` 绑定租户,`login` 登录 | Topic、消息、回执、在线状态、通话信令 |
|
||||
| WebSocket(支持自定义 Header 的原生客户端) | `wss://{host}/{api_path}v0/channels` | Upgrade Header `X-Tinode-APIKey` | 同上 |
|
||||
| WebSocket(支持自定义 Header 的原生客户端) | `wss://{host}/{api_path}v0/channels` | Upgrade Header `X-MeetingIM-APIKey` | 同上 |
|
||||
| 产品 HTTP | `https://{host}/{api_path}v1/im/*` | `Authorization: Bearer <params.token>` | 好友、群、收藏、搜索、工作台和设置 |
|
||||
| 文件 HTTP | `POST /v0/file/u/`、`GET /v0/file/s/{file_id}` | 当前用 `X-Tinode-Auth: token <base64_token>` | 文件上传下载;禁止 Query 传 Token |
|
||||
| 文件 HTTP | `POST /v0/file/u/`、`GET /v0/file/s/{file_id}` | 当前用 `X-MeetingIM-Auth: token <base64_token>` | 文件上传下载;禁止 Query 传 Token |
|
||||
|
||||
HTTP 请求统一通过 `X-Tinode-APIKey` 携带。浏览器 WebSocket 无法设置自定义 Upgrade Header 时才使用 `apikey` Query;日志和监控必须对该参数脱敏。产品 HTTP 还必须带 `X-IM-Schema: 1` 和 `X-Request-ID`;写操作带 `Idempotency-Key`。生产环境只允许 HTTPS/WSS。Token、密码、验证码、证件号不得写入 URL、普通日志、埋点或崩溃报告。
|
||||
HTTP 请求统一通过 `X-MeetingIM-APIKey` 携带。浏览器 WebSocket 无法设置自定义 Upgrade Header 时才使用 `apikey` Query;日志和监控必须对该参数脱敏。产品 HTTP 还必须带 `X-IM-Schema: 1` 和 `X-Request-ID`;写操作带 `Idempotency-Key`。生产环境只允许 HTTPS/WSS。Token、密码、验证码、证件号不得写入 URL、普通日志、埋点或崩溃报告。
|
||||
|
||||
WebSocket Upgrade 阶段由 `server/hdl_websock.go` 先调用 `checkAPIKey`。缺少或无效时不会建立 WebSocket,直接返回 HTTP 403:
|
||||
|
||||
@@ -221,7 +221,7 @@ WebSocket Upgrade 阶段由 `server/hdl_websock.go` 先调用 `checkAPIKey`。
|
||||
```http
|
||||
POST /v0/channels/lp HTTP/1.1
|
||||
Host: im.example.com
|
||||
X-Tinode-APIKey: <预置的普通 API Key>
|
||||
X-MeetingIM-APIKey: <预置的普通 API Key>
|
||||
Content-Length: 0
|
||||
```
|
||||
|
||||
@@ -235,7 +235,7 @@ Content-Length: 0
|
||||
|
||||
```http
|
||||
POST /v0/channels/lp?sid=session-id HTTP/1.1
|
||||
X-Tinode-APIKey: <预置的普通 API Key>
|
||||
X-MeetingIM-APIKey: <预置的普通 API Key>
|
||||
Content-Type: application/json
|
||||
|
||||
{"hi":{"id":"hi-1","ver":"0.25","ua":"android/1.0.0","platf":"android","lang":"zh-CN","tenant":"acme"}}
|
||||
@@ -245,7 +245,7 @@ POST 只负责把命令送入 Session。客户端再保持一个不带 Body 的
|
||||
|
||||
```http
|
||||
GET /v0/channels/lp?sid=session-id HTTP/1.1
|
||||
X-Tinode-APIKey: <预置的普通 API Key>
|
||||
X-MeetingIM-APIKey: <预置的普通 API Key>
|
||||
```
|
||||
|
||||
收到 `hi` 成功后,以相同方式 POST `{login}`,再 GET 登录结果;登录成功后依次 POST `{sub me}`、`{sub fnd}` 和会话订阅,并持续发起下一次 GET 等待下行消息。
|
||||
@@ -270,7 +270,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
本节用于 WebSocket 联调。除特别说明外:
|
||||
|
||||
- WebSocket 地址为 `wss://{host}/{api_path}v0/channels?apikey={api_key}`;支持自定义 Header 的原生客户端也可用 `X-Tinode-APIKey`。
|
||||
- WebSocket 地址为 `wss://{host}/{api_path}v0/channels?apikey={api_key}`;支持自定义 Header 的原生客户端也可用 `X-MeetingIM-APIKey`。
|
||||
- 连接建立后第一帧必须是 `{hi}`,`hi` 成功后才能 `{login}` 或 `{acc}`。
|
||||
- 每个上行命令都带客户端生成的 `id`,客户端用该 `id` 匹配 `{ctrl}`;同一连接内保持唯一即可。
|
||||
- 服务端下行可能乱序到达,客户端不能假设 `{ctrl}` 一定先于 `{meta}` 或 `{data}`。
|
||||
@@ -336,7 +336,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
##### 0.5.4.6 系统通知、好友和群业务下行
|
||||
|
||||
服务端主动下行分两类:Tinode 原生 Topic 消息使用 `{data}`、`{info}`、`{pres}` 等帧;IM 产品业务事件使用 `{info}` 帧下发,前端按 `info.what + info.event` 分发刷新。产品业务事件不占普通聊天 `seq`,不等同于系统通知列表记录;系统消息入口的未读数来自 `im_system_notifications` 和 `GET /v1/im/system-notifications`。
|
||||
服务端主动下行分两类:MeetingIM 原生 Topic 消息使用 `{data}`、`{info}`、`{pres}` 等帧;IM 产品业务事件使用 `{info}` 帧下发,前端按 `info.what + info.event` 分发刷新。产品业务事件不占普通聊天 `seq`,不等同于系统通知列表记录;系统消息入口的未读数来自 `im_system_notifications` 和 `GET /v1/im/system-notifications`。
|
||||
|
||||
用户维度业务事件统一格式:
|
||||
|
||||
@@ -425,8 +425,8 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
| WebSocket `login basic` | `{"login":{"id":"login-1","scheme":"basic","secret":"base64(username:password)"}}` | `{"ctrl":{"id":"login-1","code":200,"params":{"user":"usr...","token":"token...","expires":"2026-09-03T09:00:00Z","authlvl":"auth"}}}` |
|
||||
| WebSocket `acc new` | `{"acc":{"id":"acc-1","user":"new","scheme":"basic","username":"alice","phone":"15500000000","secret":"base64(alice:password)","login":true,"cred":[{"meth":"tel","val":"15500000000","resp":"verification_token","params":{"challenge_id":"chg_123"}}]}}` | `{"ctrl":{"id":"acc-1","code":200,"params":{"user":"usr...","username":"alice","token":"token...","expires":"2026-09-03T09:00:00Z"}}}` |
|
||||
| `POST /v0/channels/lp` | Long Polling 首包 `{"hi":{"id":"hi-1","ver":"0.25","tenant":"default"}}` | `{"ctrl":{"id":"hi-1","code":201,"params":{"sid":"lp_sid_123"}}}` |
|
||||
| `POST /v0/file/u/` | Multipart 文件;Header `X-Tinode-Auth: token <base64_token>`;业务表单可带 `purpose=chat_file&topic=grp...` | `{"ctrl":{"code":200,"params":{"url":"/v0/file/s/file123","name":"a.pdf","size":1024,"mime":"application/pdf"}}}` |
|
||||
| `GET /v0/file/s/{file_id}` | Header `X-Tinode-Auth: token <base64_token>`,可带 `Range: bytes=0-` | 返回文件字节流;失败返回 `FILE_FORBIDDEN` 或 `FILE_UNAVAILABLE` |
|
||||
| `POST /v0/file/u/` | Multipart 文件;Header `X-MeetingIM-Auth: token <base64_token>`;业务表单可带 `purpose=chat_file&topic=grp...` | `{"ctrl":{"code":200,"params":{"url":"/v0/file/s/file123","name":"a.pdf","size":1024,"mime":"application/pdf"}}}` |
|
||||
| `GET /v0/file/s/{file_id}` | Header `X-MeetingIM-Auth: token <base64_token>`,可带 `Range: bytes=0-` | 返回文件字节流;失败返回 `FILE_FORBIDDEN` 或 `FILE_UNAVAILABLE` |
|
||||
|
||||
### 0.6 Topic 与产品消息
|
||||
|
||||
@@ -481,7 +481,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
**企业解析接口:**
|
||||
|
||||
- `POST /v1/im/tenants/resolve` 未登录可调用,但必须带 `X-Tinode-APIKey` 和 `X-IM-Schema: 1`;Header 传 `X-Tenant-Code: acme`,Body 可传 `{"tenant_code":"acme","platform":"android","app_version":"1.0.0"}`。
|
||||
- `POST /v1/im/tenants/resolve` 未登录可调用,但必须带 `X-MeetingIM-APIKey` 和 `X-IM-Schema: 1`;Header 传 `X-Tenant-Code: acme`,Body 可传 `{"tenant_code":"acme","platform":"android","app_version":"1.0.0"}`。
|
||||
- 成功数据:`tenant{code,name,tenant_desc,branding}`、`endpoints{websocket,api,file}`、`auth_methods`、`password_policy`、`app_update`。不得返回 `tenant_id` 或 `tenant_ticket`。
|
||||
- 后续:保存公开企业信息,连接响应给出的 WebSocket 地址,仍然发送 0.5 节的 `hi(tenant)` 做最终租户绑定;`hi` 成功后才进入 1.2。
|
||||
- 目标失败协议:企业不存在、停用或不允许登录统一返回 `TENANT_UNAVAILABLE`;客户端不得区分不存在和停用。网络失败保留输入并允许重试。
|
||||
@@ -530,7 +530,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
- 可选字段:`license_file_id` 营业执照图片文件 ID,`enterprise_email` 企业邮箱。邮箱用于接收审核结果和后续通知,填写时必须符合邮箱格式。
|
||||
- 扫描识别:扫码或 OCR 只能作为填充辅助,提交前仍以输入框中的 `credit_code` 为准;识别失败不阻塞手动填写。
|
||||
- 图片上传:营业执照先调用公开用途受限上传接口,`purpose=enterprise_license`,支持 `jpg/png/webp/pdf`,单文件不超过 10MB。服务端通过当前 media handler 存储对象,生产环境必须配置 `oss` handler;上传成功返回 `file_id` 后再提交申请;未上传营业执照时 `license_file_id` 可为空。
|
||||
- 提交接口:`POST /v1/im/tenant-applications`,未登录可调用,必须带 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID` 和 `Idempotency-Key`。
|
||||
- 提交接口:`POST /v1/im/tenant-applications`,未登录可调用,必须带 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID` 和 `Idempotency-Key`。
|
||||
- 请求体:
|
||||
|
||||
```json
|
||||
@@ -581,7 +581,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
- 使用场景:企业码不可用、企业注册资料提交异常、审核通知未收到、登录入口无法进入等未登录阶段问题。
|
||||
- 输入字段:`description` 必填,长度 10~1000 字符;`contact` 可选,用于客服回访;`tenant_code_hint` 可选,来自用户输入;`screenshot_file_ids` 最多 9 个。
|
||||
- 截图上传:截图先调用公开用途受限上传接口,`purpose=tenant_entry_feedback`,支持 `jpg/png/webp`,单张不超过 10MB。服务端通过当前 media handler 存储对象,生产环境必须配置 `oss` handler;上传失败时允许单张重试或删除。
|
||||
- 提交接口:`POST /v1/im/tenant-entry-feedback`,未登录可调用,必须带 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID` 和 `Idempotency-Key`。
|
||||
- 提交接口:`POST /v1/im/tenant-entry-feedback`,未登录可调用,必须带 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID` 和 `Idempotency-Key`。
|
||||
- 请求体:
|
||||
|
||||
```json
|
||||
@@ -619,8 +619,8 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
- 前端动作:账号、密码非空且已勾选协议后启用登录;密码仅驻留当前页面内存。
|
||||
- 协议:已完成 `hi` 的 WebSocket 发送 `{login scheme:"basic"}`,`secret=base64(username:password)`;Base64 不是加密,必须通过 WSS 传输,不得先登录再传企业码。
|
||||
- 成功:读取 `{ctrl params.user/token/expires/authlvl}`,Token 存 Keychain/Keystore;立即 `sub me`,再加载会话。前端不解码 Token,也不再次 Base64 编码。
|
||||
- 产品 HTTP:使用同一个 `params.token` 作为 `Authorization: Bearer <params.token>`;所有 `/v1/im/*` HTTP 请求仍必须带 `X-Tinode-APIKey`、`X-IM-Schema: 1`,写请求再带 `Idempotency-Key`。
|
||||
- Token:当前复用 Tinode 单一登录 Token,默认有效期 14 天,不使用 Refresh Token。有效 Token 登录成功会签发新的 14 天 Token,客户端覆盖旧值;过期后重新账号密码登录。Token 已绑定 `tenant_id/user_id/auth_version`,修改密码、封禁账号后旧 Token 应失效。
|
||||
- 产品 HTTP:使用同一个 `params.token` 作为 `Authorization: Bearer <params.token>`;所有 `/v1/im/*` HTTP 请求仍必须带 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`,写请求再带 `Idempotency-Key`。
|
||||
- Token:当前复用 MeetingIM 单一登录 Token,默认有效期 14 天,不使用 Refresh Token。有效 Token 登录成功会签发新的 14 天 Token,客户端覆盖旧值;过期后重新账号密码登录。Token 已绑定 `tenant_id/user_id/auth_version`,修改密码、封禁账号后旧 Token 应失效。
|
||||
- 密码:服务端使用 `bcrypt.DefaultCost=10` 生成单向哈希,`im_auth.secret` 只保存哈希;客户端和服务端不得记录密码或完整 Basic `secret`。
|
||||
- 错误:`AUTH_FAILED` 统一显示账号或密码错误;`TENANT_MISMATCH` 清 Token 并回企业码页;`ACCOUNT_DISABLED`、`REALNAME_REQUIRED`、`YOUTH_RESTRICTED` 按专用页面处理。
|
||||
|
||||
@@ -778,7 +778,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -842,7 +842,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
**状态:基础消息操作部分已实现;产品权限矩阵需改造。**
|
||||
|
||||
- 长按本身不请求。客户端根据消息的 `type/from/seq/created_at/status`、当前 Topic 权限和服务端下发的 `message_policy` 预裁剪菜单。
|
||||
- 引用/复制为本地动作;收藏见 4.16;转发见 4.17~4.20;删除使用 Tinode `{del what:"msg",topic,delseq}`;撤回需新增 `POST /v1/im/topics/{topic}/messages/{seq}/recall`。
|
||||
- 引用/复制为本地动作;收藏见 4.16;转发见 4.17~4.20;删除使用 MeetingIM `{del what:"msg",topic,delseq}`;撤回需新增 `POST /v1/im/topics/{topic}/messages/{seq}/recall`。
|
||||
- 编辑使用 `POST /v1/im/topics/{topic}/messages/{seq}/revisions`,Body `{"content":...,"client_mid":"..."}`;仅文本且在时限内允许。
|
||||
- 群回执调用 `GET /v1/im/topics/{topic}/messages/{seq}/receipts?cursor=`。所有最终操作由服务端验证消息归属、时限、群角色和租户。
|
||||
|
||||
@@ -861,7 +861,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -1194,7 +1194,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -1361,7 +1361,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
**状态:图片文件名与画面语义不一致;按“清除聊天记录”实施,需改造。**
|
||||
|
||||
- 确认调用 Tinode `{del what:"msg",topic,delseq:[{"low":1,"hi":last_seq+1}],hard:false}`,仅删除当前用户视图;或封装 `DELETE /v1/im/conversations/{topic}/messages`。
|
||||
- 确认调用 MeetingIM `{del what:"msg",topic,delseq:[{"low":1,"hi":last_seq+1}],hard:false}`,仅删除当前用户视图;或封装 `DELETE /v1/im/conversations/{topic}/messages`。
|
||||
- 不解除好友、不影响对方历史、不删除收藏;附件仅在无任何有效引用且过保留期后回收。
|
||||
- 前端需在确认文案明确“仅清除自己的聊天记录”,成功后清本地 Topic 消息缓存并保留会话关系。
|
||||
|
||||
@@ -1369,7 +1369,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -1404,7 +1404,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
<img src="images/群聊.png" alt="群聊" width="360">
|
||||
|
||||
**状态:Tinode 群 Topic 已实现基础能力;产品群列表与配额需改造。**
|
||||
**状态:MeetingIM 群 Topic 已实现基础能力;产品群列表与配额需改造。**
|
||||
|
||||
- 列表:`GET /v1/im/groups?category=owned|managed|joined&query=&cursor=`,返回 `topic,name,avatar_file_id,member_count,my_role,updated_at`。
|
||||
- 创建:`POST /v1/im/groups`,Body `{"name":"...","description":"...","member_user_ids":[],"avatar_file_id":"..."}`;`description` 可省略或传空字符串,最长 200 字符;原子校验租户群数上限和群成员上限,返回 `topic,name,avatar_file_id,description,owner,member_count,version,permissions`。
|
||||
@@ -1677,7 +1677,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -1812,7 +1812,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
**状态:底层下载已实现租户校验;资源 ACL 需改造。**
|
||||
|
||||
- 客户端使用 `GET /v0/file/s/{file_id}`,Header 传 API Key 与 `X-Tinode-Auth: token <base64_token>`;禁止 `?auth=&secret=`。
|
||||
- 客户端使用 `GET /v0/file/s/{file_id}`,Header 传 API Key 与 `X-MeetingIM-Auth: token <base64_token>`;禁止 `?auth=&secret=`。
|
||||
- 服务端除 Token 租户外,还必须校验该用户通过消息、群文件或收藏拥有有效引用,并支持 `Range`、`ETag`、内容长度和安全文件名。
|
||||
- 下载前客户端校验本地空间和网络策略;`FILE_FORBIDDEN` 不自动重试,`FILE_UNAVAILABLE` 显示失效。
|
||||
|
||||
@@ -1885,7 +1885,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -2022,7 +2022,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -2059,6 +2059,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
- 根节点:`GET /v1/im/organization/departments?parent_id=root&cursor=`;子部门同接口传 `parent_id`;成员 `GET /v1/im/organization/departments/{id}/members?cursor=`。
|
||||
- 部门返回 `department_id,name,parent_id,child_count,member_count,version`;成员只返回当前查看人可见字段。
|
||||
- 全局搜索:`GET /v1/im/organization/search?q=&types=department,user&cursor=`。服务端执行组织范围授权,离职用户标记不可联系或从结果移除。
|
||||
- 组织架构可见范围由服务端按当前登录用户裁剪:上架测试账号可看全部组织;手机号注册账号默认只能看到自己与好友所在组织路径及成员;邀请码注册账号默认只能看到自己所在组织路径及本人。上架测试账号通过租户业务库 `im_org_visibility_overrides` 配置 `visibility_scope=all`,客户端不传可见范围参数。
|
||||
|
||||
### 9.3 会议通知-发起人状态.png
|
||||
|
||||
@@ -2173,7 +2174,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -2230,10 +2231,10 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
<img src="images/个人信息.png" alt="个人信息" width="360">
|
||||
|
||||
**状态:Tinode `me` 资料更新已有基础;目标产品接口需改造。**
|
||||
**状态:MeetingIM `me` 资料更新已有基础;目标产品接口需改造。**
|
||||
|
||||
- 查询 `GET /v1/im/me/profile` 返回 `avatar_file_id,nickname,birth_date,signature,gender,region,email,public_account,version,field_rules`;`email` 当前仅为资料字段,不用于登录或找回密码。
|
||||
- 更新统一使用 `PATCH /v1/im/me/profile`,仅提交变更字段并带 `version`;服务端更新后同步 Tinode `me.public` 并推送资料事件。
|
||||
- 更新统一使用 `PATCH /v1/im/me/profile`,仅提交变更字段并带 `version`;服务端更新后同步 MeetingIM `me.public` 并推送资料事件。
|
||||
- 头像先以 `purpose=user_avatar` 上传再 PATCH;任何字段的可见性由隐私策略裁剪。
|
||||
|
||||
### 10.3 设置昵称.png
|
||||
@@ -2420,7 +2421,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -2505,7 +2506,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
以下示例用于本章 HTTP 联调快速查阅。除特别说明外:
|
||||
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-Tinode-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 产品 HTTP 均使用 `https://{host}/{api_path}v1/im`,请求头包含 `X-MeetingIM-APIKey`、`X-IM-Schema: 1`、`X-Request-ID`;登录后接口再带 `Authorization: Bearer <token>`。
|
||||
- 写接口必须带 `Idempotency-Key`。二次认证接口按正文说明额外带 `X-Action-Token` 或 `X-Risk-Action-Token`。
|
||||
- 成功响应统一包裹为 `{"code":0,"data":示例,"request_id":"...","server_time":"..."}`;下表只展示 `data`。
|
||||
- 失败响应统一包裹为 `{"code":30000,"reason":"MALFORMED_REQUEST","message":"...","details":{},"request_id":"...","server_time":"..."}`。
|
||||
@@ -2527,7 +2528,7 @@ X-Tinode-APIKey: <预置的普通 API Key>
|
||||
|
||||
1. WebSocket `/v0/channels`、Wire Version `0.25` 和最低版本 `0.20`。
|
||||
2. 第一条 `hi` 携带企业码并固定 Session 租户;响应包含公开租户信息、限制、ICE 配置和呼叫超时。
|
||||
3. `basic`/`token` 登录,`sub/get/set/pub/leave/del/note` 基础 Tinode 协议。
|
||||
3. `basic`/`token` 登录,`sub/get/set/pub/leave/del/note` 基础 MeetingIM 协议。
|
||||
4. `pub` 成功返回 `202 + seq`,Topic 消息与基础回执同步。
|
||||
5. `/v0/file/u/` 和 `/v0/file/s/{file_id}` 的基础上传下载及租户存储隔离。
|
||||
|
||||
|
||||
@@ -443,6 +443,19 @@ CREATE TABLE IF NOT EXISTS tinode.im_org_members (
|
||||
CONSTRAINT fk_im_org_members_department FOREIGN KEY (department_id) REFERENCES tinode.im_org_departments(department_id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tinode.im_org_visibility_overrides (
|
||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||
user_id BIGINT NOT NULL,
|
||||
visibility_scope VARCHAR(16) NOT NULL,
|
||||
state VARCHAR(16) NOT NULL DEFAULT 'active',
|
||||
remark VARCHAR(256) NOT NULL DEFAULT '',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE INDEX uk_im_org_visibility_user (user_id),
|
||||
INDEX idx_im_org_visibility_scope (visibility_scope, state)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tinode.im_meetings (
|
||||
id BIGINT NOT NULL AUTO_INCREMENT,
|
||||
meeting_id VARCHAR(64) NOT NULL,
|
||||
|
||||
+2
-1
@@ -280,6 +280,7 @@
|
||||
10. 会议创建、变更、取消、提醒和参会回应已生成在线事件与系统通知,关键变更在事务内写 Outbox。
|
||||
11. 组织全局成员接口 `GET /v1/im/organization/members` 已具备。
|
||||
12. 月报 reopen `POST /v1/im/reports/monthly/{id}/reopen` 已具备。
|
||||
13. 组织架构可见范围已按账号来源裁剪:邀请码注册默认仅本人,手机号注册默认本人和好友组织路径,上架测试账号可通过 `im_org_visibility_overrides.visibility_scope=all` 放开全量。
|
||||
|
||||
### 9.2 后续增强项
|
||||
|
||||
@@ -288,7 +289,7 @@
|
||||
| P0 | 工作台权限与功能开关配置化 | 当前模块基线可返回,后续需要按租户、部门、角色、后台配置动态裁剪。 | 不同用户登录同一租户看到不同授权模块。 |
|
||||
| P0 | 工作台未读角标实时事件 | `workbench_total_unread` 已有,后续需要模块未读聚合和 `workbench.badge.updated` 增量事件。 | 会议、日报、信箱未读变化后工作台角标实时更新。 |
|
||||
| P0 | 组织数据后台维护链路 | 当前前台读接口和表已具备,后续需要后台导入、增删改部门、调整成员和离职状态。 | 后台修改组织后前台接口版本变化,客户端可刷新。 |
|
||||
| P0 | 组织权限与可见字段裁剪 | 成员手机号、邮箱、职位等字段需要按组织角色、隐私和企业策略裁剪。 | 普通员工和管理员看到的成员字段不同且不可绕过。 |
|
||||
| P0 | 组织字段级隐私策略 | 组织架构范围裁剪已具备,成员手机号、邮箱、职位等字段后续仍需按组织角色、隐私和企业策略进一步细化。 | 普通员工和管理员看到的成员字段不同且不可绕过。 |
|
||||
| P1 | 组织全局成员接口深度联调 | `GET /v1/im/organization/members` 已具备,仍需按部门、关键词、权限和分页做测试环境回归。 | 前端可直接分页查询并按部门过滤,字段裁剪符合权限。 |
|
||||
| P1 | 会议列表完整联调 | 对接文档标注 `GET /v1/im/meetings?cursor=` 待补列表;代码有 `serveIMMeetings`,仍需用测试数据确认返回结构。 | 会议列表、详情、响应、取消端到端一致。 |
|
||||
| P1 | 月报 reopen 审计与权限扩展 | reopen 接口已具备,后续需要后台权限、原因记录、审计和通知闭环。 | 已提交月报可按权限退回草稿并保留审计。 |
|
||||
|
||||
Reference in New Issue
Block a user