当前用户
获取当前认证用户的身份信息,以及管理「我的凭证」(API Key、Agent Token、OAuth 授权)。
源码: apps/backend/src/routes/my.ts
GET /my
返回当前认证方式及其关联信息。
认证方式
JWT Token / API Key / Agent Token(combinedAuth)
请求参数
无
响应格式
状态码: 200
响应内容取决于认证方式:
JWT 认证响应
{
"method": "jwt",
"userId": "uuid",
"email": "user@example.com",
"metadata": {
"display_name": "用户名",
"avatar_url": "https://..."
}
}| 字段 | 类型 | 说明 |
|---|---|---|
method | string | 固定值 "jwt" |
userId | string | 用户 UUID |
email | string | 用户邮箱 |
metadata | object | 用户元数据(user_metadata) |
API Key 认证响应
{
"method": "api-key",
"userId": "uuid",
"teamId": "uuid",
"apiKeyId": "uuid"
}| 字段 | 类型 | 说明 |
|---|---|---|
method | string | 固定值 "api-key" |
userId | string | API Key 创建者的用户 ID |
teamId | string | API Key 所属团队 ID |
apiKeyId | string | API Key 记录 ID |
Agent Token 认证响应
{
"method": "agent",
"userId": "uuid",
"teamId": "uuid",
"bindingId": "uuid"
}| 字段 | 类型 | 说明 |
|---|---|---|
method | string | 固定值 "agent" |
userId | string | Agent 关联的用户 ID |
teamId | string | Agent 所属团队 ID |
bindingId | string | agent_bindings 记录 ID |
Agent Token 需在其权限组中显式授予
GET /my访问权限才会到达本端点;未授权时由combinedAuth的checkTokenPermission拦截。
Schedule 认证响应
{
"method": "schedule",
"scheduleId": "uuid",
"teamId": "uuid",
"deploymentId": "uuid"
}| 字段 | 类型 | 说明 |
|---|---|---|
method | string | 固定值 "schedule" |
scheduleId | string | 定时任务 ID |
teamId | string | 所属团队 ID |
deploymentId | string | 目标部署 ID |
请求示例
# JWT 认证
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
https://block2-api.wainao.chat/my
# API Key 认证
curl -H "Authorization: Bearer wn-your-api-key" \
https://block2-api.wainao.chat/my
# Agent Token 认证
curl -H "Authorization: Bearer wna-your-agent-token" \
https://block2-api.wainao.chat/my错误码
| 状态码 | 错误 | 说明 |
|---|---|---|
| 401 | Missing or invalid authorization header | 缺少认证信息 |
| 401 | Invalid API key / Invalid token | 认证失败 |
| 403 | Permission denied: ... | Token 权限组不包含 GET /my |
POST /my/default-project/ensure
幂等创建或返回当前用户的「个人默认项目」。移动端录音、硬件等个人默认数据先调用此端点拿到 project.id,再复用 POST /storage/:projectId/upload 上传。
认证方式
接受:
- JWT Token
- OAuth Access Token(
wno-...),且 token scopes 必须覆盖mobile:full
API Key、Agent Token、Schedule Token 即使认证有效,也会被子路由 guard 拒绝。OAuth 场景下,RPC 的 p_user_id 始终来自 auth.userId,不会读取 body/query 中的用户 ID。
请求体
{
"lang": "zh-CN"
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
lang | string | 否 | 命名语言。缺省时使用 Accept-Language 首段,再按 X-Server-Mode 兜底。 |
响应格式
{
"success": true,
"data": {
"team": {
"id": "uuid",
"slug": "team-slug",
"name": "我的团队"
},
"project": {
"id": "uuid",
"team_id": "uuid",
"slug": "personal-space",
"name": "个人空间",
"system_purpose": "personal_default"
},
"permissions": {
"storage_write": true,
"deletion_locked": true
}
}
}行为说明
- 幂等:同一用户重复调用返回同一个 active
personal_default项目。 - 按需创建:不会在登录或
/auth/initialize时预建。 - 归属:项目落在用户本人拥有的 active team 下;不会落到别人邀请用户加入的协作团队。
- 可见性:项目在 Web 项目列表可见,但不可删除、不可设为公开;项目内改名、编辑、上传仍可正常进行。
- 存储:拿到
project.id后,直接调用POST /storage/{project.id}/upload。
错误码
| 状态码 | 错误 | 说明 |
|---|---|---|
| 401 | Missing or invalid authorization header / Invalid token / Invalid or revoked OAuth token / OAuth token has expired | 缺少认证或 token 无效、过期、撤销 |
| 403 | insufficient_scope | OAuth token 有效,但 scope 不包含 mobile:full 对本路由的授权 |
| 403 | This endpoint only accepts JWT or OAuth authentication | 凭证有效但不是 JWT/OAuth(例如 API Key、Agent Token) |
| 409 | personal_default_project_invalid_team | 既有 personal_default 项目挂在非本人 owned team 或已删除 team,需人工修复数据 |
| 500 | internal_error | RPC 调用失败或返回结构异常 |
我的凭证管理(/my/credentials/*)
「我的凭证」管理子路由组,仅接受 JWT 认证。其他认证方式(API Key / Agent Token)通过 combinedAuth 后会被 jwtOnly guard 拦截返回 403;OAuth token 不在 mobile:full 白名单内,会返回 403 insufficient_scope;无效 token 在认证阶段直接 401 拒绝。
设计意图:用户对自己持有的机器凭证(Agent Token、OAuth 授权)的管理能力,必须使用人类身份(JWT)操作,避免机器凭证自我撤销。
API Key 列表与撤销复用既有
/teams/:teamId/api-keys链路,未在此暴露独立 REST 端点。
GET /my/credentials/agent-tokens
列出当前用户持有的 active Agent Token 绑定。
过滤条件: owner_user_id = auth.userId AND token_hash IS NOT NULL AND deleted_at IS NULL,按创建时间倒序。
响应格式
{
"items": [
{
"binding_id": "uuid",
"agent_user_id": "uuid",
"agent_display_name": "我的 Agent",
"agent_avatar_url": "https://...",
"team_id": "uuid",
"team_name": "团队名",
"team_slug": "team-slug",
"can_send": true,
"can_receive": true,
"created_at": "2026-04-25T..."
}
]
}| 字段 | 类型 | 说明 |
|---|---|---|
binding_id | string | agent_bindings 主键,吊销时使用 |
agent_user_id | string | Agent 对应的虚拟用户 ID |
agent_display_name | string | null | Agent 在 profiles 表中的展示名 |
agent_avatar_url | string | null | Agent 头像 URL |
team_id / team_name / team_slug | string | null | Agent 所属团队(可能为空,代表个人 Agent) |
can_send / can_receive | boolean | Agent 当前的双向通信开关 |
created_at | string | Agent 绑定创建时间(ISO 8601) |
DELETE /my/credentials/agent-tokens/:bindingId
吊销指定 Agent Token,写 token_hash = null 保留绑定本体(与 /team-agents/.../revoke-token 行为一致)。
响应格式
成功(首次撤销):
{ "success": true }幂等(已撤销过):
{ "success": true, "alreadyRevoked": true }错误码
| 状态码 | 错误 | 说明 |
|---|---|---|
| 401 | Missing or invalid authorization header / Invalid token | 缺少认证或 token 无效(在 combinedAuth 阶段拦截) |
| 403 | This endpoint only accepts JWT authentication | 凭证有效但非 JWT(API Key / Agent Token 通过 combinedAuth 后由 jwtOnly guard 拒绝) |
| 403 | Forbidden | binding 不属于当前用户 |
| 404 | Agent binding not found | binding 不存在或已软删除 |
| 500 | Failed to revoke agent token | 数据库写入失败 |
GET /my/credentials/agent-bindings-as-agent
被绑视角(2026-06-10 新增):列出哪些团队把当前用户绑定为 Agent(agent_bindings.agent_user_id = auth.userId AND deleted_at IS NULL)。与上面的 agent-tokens(我授权给别人的)互为对称视角。
响应格式
{
"items": [
{
"binding_id": "uuid",
"owner_user_id": "uuid",
"owner_display_name": "授权人昵称",
"team_id": "uuid",
"team_name": "团队名",
"team_slug": "team-slug",
"can_send": true,
"can_receive": true,
"created_at": "2026-06-10T08:00:00.000Z"
}
]
}DELETE /my/credentials/agent-bindings-as-agent/:bindingId
被绑方主动解除 Agent 绑定:软删除整条 binding 并同时置空 token_hash(与团队侧删除 Agent 同语义),解除后该团队不能再通过此绑定调用当前用户。权限校验按 agent_user_id = auth.userId。
响应 200
{ "success": true }错误码
| 状态码 | 错误 | 说明 |
|---|---|---|
| 403 | Forbidden | binding 的被绑方不是当前用户 |
| 404 | Agent binding not found | binding 不存在或已软删除 |
| 500 | Failed to remove agent binding | 数据库写入失败 |
GET /my/credentials/oauth-authorizations
列出当前用户授权过的第三方 OAuth 应用,按 app_id 聚合(仅展示 active token,且应用未被软删除)。
过滤条件: oauth_tokens.user_id = auth.userId AND oauth_tokens.revoked_at IS NULL AND oauth_apps.deleted_at IS NULL
聚合规则: 同一应用的多枚 token 合并为一条;scopes 取并集;authorized_at 取最新;active_token_count 计数。
响应格式
{
"items": [
{
"app_id": "uuid",
"app_name": "我的应用",
"app_logo_url": "https://...",
"scopes": ["documents:read", "runs:write"],
"authorized_at": "2026-04-25T...",
"active_token_count": 1
}
]
}已禁用的应用(
disabled_at IS NOT NULL)仍会展示,让用户感知后主动撤销。已删除的应用(deleted_at IS NOT NULL)不展示。
DELETE /my/credentials/oauth-authorizations/:appId
撤销该应用下当前用户的所有 active token。严格按 user_id + app_id 过滤,不会影响其他用户的授权(与 admin 端的 revoke_all_oauth_tokens_for_app RPC 语义不同)。
响应格式
{ "success": true, "revokedCount": 2 }幂等:若该应用下当前用户已无 active token,返回 revokedCount: 0。
错误码
| 状态码 | 错误 | 说明 |
|---|---|---|
| 401 | Missing or invalid authorization header / Invalid token | 缺少认证或 token 无效(在 combinedAuth 阶段拦截) |
| 403 | This endpoint only accepts JWT authentication | 凭证有效但非 JWT(API Key / Agent Token 通过 combinedAuth 后由 jwtOnly guard 拒绝) |
| 500 | Failed to revoke oauth authorization | 数据库写入失败 |