X-AnyLabeling 云端同步 API v2 文档

概述

本文档描述了 X-AnyLabeling 云端同步功能的 API 接口规范(v2 版本)。v2 版本在 v1 基础上增加了多用户支持、工作空间归属、权限控制、用户数据隔离等功能。

认证方式

所有 API 请求需要在 HTTP Header 中携带 API Key:

Token: <your_api_key>

基础 URL

http://<server_host>:<server_port>

通用响应格式

成功响应

{
  "success": true,
  "data": { ... }
}

错误响应

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Error message"
  }
}

错误码表

错误码 HTTP 状态码 说明
UNAUTHORIZED 401 API Key 无效或缺失
FORBIDDEN 403 权限不足
WORKSPACE_ACCESS_DENIED 403 无权访问该工作空间
API_KEY_EXPIRED 401 API Key 已过期
WORKSPACE_CONFLICT 409 工作空间名称冲突
CLOUD_DISABLED 200 云端存储未启用
FILE_NOT_FOUND 200 文件不存在
NOT_FOUND 200 资源不存在
LIST_ERROR 200 列表操作失败
UPLOAD_ERROR 200 上传失败
DOWNLOAD_ERROR 200 下载失败
DELETE_ERROR 200 删除失败
CREATE_ERROR 200 创建失败
UPDATE_ERROR 200 更新失败
CHECKSUM_ERROR 200 校验失败
RESOLVE_ERROR 200 解析失败

API 端点

1. 用户信息

GET /v1/users/me

获取当前认证用户的信息。

请求

GET /v1/users/me
Token: <api_key>

响应

{
  "success": true,
  "data": {
    "user_id": "zhangsan",
    "name": "张三",
    "permissions": ["read", "write", "delete"]
  }
}

权限要求:无(只需有效 API Key)


2. 连接管理

POST /v1/cloud/connect

验证连接并返回工作空间状态和用户信息。

请求

POST /v1/cloud/connect
Token: <api_key>

响应

{
  "success": true,
  "data": {
    "status": "connected",
    "storage_type": "minio",
    "user": {
      "user_id": "zhangsan",
      "name": "张三",
      "permissions": ["read", "write", "delete"]
    }
  }
}

权限要求:无(只需有效 API Key)


POST /v1/cloud/disconnect

断开连接(无状态 API,实际为占位端点)。

请求

POST /v1/cloud/disconnect
Token: <api_key>

响应

{
  "success": true,
  "data": {
    "message": "disconnected"
  }
}

权限要求:无


3. 工作空间管理

GET /v1/cloud/workspaces

列出当前用户有权访问的所有工作空间。

请求

GET /v1/cloud/workspaces
Token: <api_key>

响应

{
  "success": true,
  "data": [
    {
      "workspace": "project-a",
      "owner": "zhangsan",
      "local_path": "/data/project-a",
      "display_name": "Project A",
      "description": "标注项目 A",
      "created_at": "2026-06-23T10:00:00+00:00",
      "updated_at": "2026-06-23T10:30:00+00:00"
    },
    {
      "workspace": "project-b",
      "owner": "zhangsan",
      "local_path": "/data/project-b",
      "display_name": "Project B",
      "description": "标注项目 B",
      "created_at": "2026-06-23T09:00:00+00:00",
      "updated_at": "2026-06-23T09:30:00+00:00"
    }
  ]
}

字段说明

  • workspace: 工作空间唯一标识
  • owner: 工作空间所有者 user_id
  • local_path: 本地文件夹路径
  • display_name: 显示名称
  • description: 描述
  • created_at: 创建时间(ISO 8601)
  • updated_at: 更新时间(ISO 8601)

权限要求read


POST /v1/cloud/workspaces

创建新的工作空间。工作空间所有者自动设置为当前用户。

请求

POST /v1/cloud/workspaces?workspace=project-c&local_path=/data/project-c&display_name=Project%20C&description=New%20project
Token: <api_key>

查询参数

  • workspace (必需): 工作空间唯一标识
  • local_path (可选): 本地文件夹路径
  • display_name (可选): 显示名称
  • description (可选): 描述

响应

{
  "success": true,
  "data": {
    "workspace": "project-c",
    "owner": "zhangsan",
    "local_path": "/data/project-c",
    "display_name": "Project C",
    "description": "New project",
    "created_at": "2026-06-23T11:00:00+00:00",
    "updated_at": "2026-06-23T11:00:00+00:00"
  }
}

权限要求write


PUT /v1/cloud/workspaces/{workspace}

更新工作空间配置。只有工作空间所有者或管理员可以执行此操作。

请求

PUT /v1/cloud/workspaces/project-a?local_path=/new/path&display_name=New%20Name
Token: <api_key>

路径参数

  • workspace: 工作空间标识

查询参数

  • local_path (可选): 新的本地文件夹路径
  • display_name (可选): 新的显示名称
  • description (可选): 新的描述

响应

{
  "success": true,
  "data": {
    "workspace": "project-a",
    "owner": "zhangsan",
    "local_path": "/new/path",
    "display_name": "New Name",
    "description": "Updated description",
    "created_at": "2026-06-23T10:00:00+00:00",
    "updated_at": "2026-06-23T12:00:00+00:00"
  }
}

权限要求write + 工作空间所有者或管理员


DELETE /v1/cloud/workspaces/{workspace}

删除工作空间配置(不会删除实际文件)。只有工作空间所有者或管理员可以执行此操作。

请求

DELETE /v1/cloud/workspaces/project-a
Token: <api_key>

响应

{
  "success": true,
  "data": {
    "workspace": "project-a",
    "deleted": true
  }
}

权限要求delete + 工作空间所有者或管理员


4. 文件操作

GET /v1/cloud/workspaces/{workspace}/files

列出工作空间中的所有文件。

请求

GET /v1/cloud/workspaces/project-a/files
Token: <api_key>

响应

{
  "success": true,
  "data": [
    {
      "name": "image_001.jpg",
      "size": 102400,
      "checksum": "d41d8cd98f00b204e9800998ecf8427e",
      "last_modified": "2026-06-23T10:30:00+00:00"
    },
    {
      "name": "image_001.json",
      "size": 2048,
      "checksum": "098f6bcd4621d373cade4e832627b4f6",
      "last_modified": "2026-06-23T10:35:00+00:00"
    }
  ]
}

字段说明

  • name: 文件名
  • size: 文件大小(字节)
  • checksum: MD5 校验和
  • last_modified: 最后修改时间(ISO 8601)

权限要求read + 工作空间访问权限


POST /v1/cloud/workspaces/{workspace}/upload

上传文件到工作空间。支持图片、JSON 标签文件和视频文件。

请求

POST /v1/cloud/workspaces/project-a/upload
Content-Type: multipart/form-data
Token: <api_key>

------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="image_002.jpg"
Content-Type: image/jpeg

<file content>
------WebKitFormBoundary
Content-Disposition: form-data; name="filename"

image_002.jpg
------WebKitFormBoundary--

表单字段

  • file (必需): 文件内容(multipart/form-data)
  • filename (必需): 目标文件名

响应

{
  "success": true,
  "data": {
    "filename": "image_002.jpg",
    "size": 102400,
    "checksum": "d41d8cd98f00b204e9800998ecf8427e"
  }
}

权限要求write + 工作空间访问权限


GET /v1/cloud/workspaces/{workspace}/download/{filename}

从工作空间下载文件。

请求

GET /v1/cloud/workspaces/project-a/download/image_001.jpg
Token: <api_key>

响应

返回文件内容,Content-Type 为 application/octet-stream

权限要求read + 工作空间访问权限


DELETE /v1/cloud/workspaces/{workspace}/files/{filename}

从工作空间删除文件。

请求

DELETE /v1/cloud/workspaces/project-a/files/image_001.jpg
Token: <api_key>

响应

{
  "success": true,
  "data": {
    "filename": "image_001.jpg",
    "deleted": true
  }
}

权限要求delete + 工作空间访问权限


GET /v1/cloud/workspaces/{workspace}/checksum/{filename}

获取文件的 MD5 校验和。

请求

GET /v1/cloud/workspaces/project-a/checksum/image_001.jpg
Token: <api_key>

响应

{
  "success": true,
  "data": {
    "filename": "image_001.jpg",
    "checksum": "d41d8cd98f00b204e9800998ecf8427e"
  }
}

权限要求read + 工作空间访问权限


6. 工作空间解析

POST /v1/cloud/workspaces/resolve

根据本地路径解析对应的工作空间。用于在打开本地文件夹时自动识别关联的云端工作空间。

请求

POST /v1/cloud/workspaces/resolve?local_path=/data/project-a
Token: <api_key>

查询参数

  • local_path (必需): 本地文件夹路径

响应

{
  "success": true,
  "data": {
    "workspace": "project-a",
    "owner": "zhangsan",
    "local_path": "/data/project-a",
    "display_name": "Project A",
    "description": "标注项目 A",
    "created_at": "2026-06-23T10:00:00+00:00",
    "updated_at": "2026-06-23T10:30:00+00:00"
  }
}

权限要求read


权限模型

权限级别

权限 说明 可访问的操作
read 读取 list_files, download, checksum, list_workspaces, resolve
write 写入 upload, create_workspace, update_workspace
delete 删除 delete_file, delete_workspace
admin 管理 所有操作

权限检查规则

  1. 管理员权限:拥有 admin 权限的用户可以执行所有操作,绕过所有工作空间访问限制
  2. 工作空间访问:只有工作空间所有者(owner)可以访问该工作空间
  3. 所有者操作:更新、删除工作空间等操作只有工作空间所有者或管理员可以执行
  4. 向后兼容:当 api_key_enabled=false 时,所有权限检查被跳过,保持 v1 行为

审计日志

所有关键操作都会记录审计日志,存储在 MinIO 的 {bucket}-audit 存储桶中。

记录的操作

  • 文件上传/下载/删除
  • 工作空间创建/更新/删除

日志格式

{
  "timestamp": "2026-06-23T11:00:00+00:00",
  "user_id": "zhangsan",
  "action": "upload",
  "workspace": "project-a",
  "resource": "image_002.jpg",
  "details": {
    "size": 102400,
    "checksum": "d41d8cd98f00b204e9800998ecf8427e"
  }
}

日志路径

{bucket}-audit/{workspace}/{YYYY}/{MM}/{DD}/{timestamp}_{user_id}_{action}.json

向后兼容性

单 API Key 模式

当配置中只有单个 api_key(而非 api_keys 列表)时,系统会自动创建一个默认的 admin 用户:

security:
  api_key_enabled: true
  api_key: "your_single_key"
  # api_keys 列表为空,自动使用 api_key

此时所有请求都被视为 admin 用户,拥有所有权限。

旧工作空间迁移

对于没有 owner 字段的旧工作空间,系统会自动添加:

{
  "workspace": "old-project",
  "owner": "__system__",
  ...
}

在单 Key 模式下,所有用户都可以访问这些工作空间。在多 Key 模式下,需要管理员重新分配归属。


配置示例

多用户模式(推荐)

security:
  api_key_enabled: true
  api_key_header: "Token"
  
  api_keys:
    - key: "user_zhangsan_key"
      user_id: "zhangsan"
      name: "张三"
      permissions: ["read", "write", "delete"]
    
    - key: "user_lisi_key"
      user_id: "lisi"
      name: "李四"
      permissions: ["read", "write"]
    
    - key: "admin_key"
      user_id: "admin"
      name: "管理员"
      permissions: ["read", "write", "delete", "admin"]
  
  api_key: ""  # 留空

单用户模式(向后兼容)

security:
  api_key_enabled: true
  api_key: "your_single_key"
  api_keys: []  # 空列表

前端集成指南

连接流程

  1. 用户输入服务器地址和 API Key
  2. 调用 POST /v1/cloud/connect
  3. 保存返回的 user 信息到本地状态
  4. 在 UI 上显示当前用户名和权限

工作空间列表

  1. 调用 GET /v1/cloud/workspaces
  2. 后端自动按当前用户的 user_id 过滤,只返回该用户自己的工作空间
  3. 工作空间列表中所有工作空间都属于当前用户(无需区分角色)

错误处理

  • 处理 401 错误:提示用户重新输入 API Key
  • 处理 403 错误:提示权限不足或无权访问该工作空间
  • 处理其他错误:显示错误消息并提供重试选项

后端改动详细说明(指导客户端修改)

设计背景与目标

v2 后端改动的核心目标是:在保持向后兼容的前提下,为云端同步功能增加多用户支持,使小团队(5-20 人)可以共享同一台服务器,每个用户有独立的身份、工作空间归属和基本权限控制。

设计原则

  1. 向后兼容:单 API Key 模式仍然可用,旧客户端无需修改即可正常工作
  2. 最小改动:尽量复用现有 API 结构,减少前端改动量
  3. 接口文档先行:所有接口变更形成文档,便于前后端同步开发
  4. 渐进式升级:客户端可以分阶段适配,先适配核心功能

后端架构改动概览

┌─────────────────────────────────────────────────────────────────┐
│  客户端 (X-AnyLabeling)                                         │
│  - sync_api.py: HTTP 请求层                                      │
│  - sync_manager.py: 业务逻辑层                                    │
│  - cloud_sync_widget.py: UI 层                                   │
└──────────────────────────┬──────────────────────────────────────┘
                           │ HTTP (Token header)
┌──────────────────────────▼──────────────────────────────────────┐
│  服务端 API 层                                                    │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  APIKeyMiddleware (middleware.py)                         │   │
│  │  - 支持多 API Key 映射                                     │   │
│  │  - 验证后注入 user_id / user_name / permissions 到 state   │   │
│  │  - 向后兼容:单 Key 自动映射为 admin 用户                    │   │
│  └──────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  cloud.py (API 端点)                                       │   │
│  │  - 所有端点新增权限检查                                      │   │
│  │  - connect 返回用户信息                                      │   │
│  │  - list_workspaces 按用户过滤                                │   │
│  │  - create_workspace 自动设置 owner                           │   │
│  └──────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  deps.py (权限检查工具)                                     │   │
│  │  - check_workspace_access: 检查工作空间访问权限              │   │
│  │  - check_workspace_owner: 检查工作空间所有者                  │   │
│  └──────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  users.py (用户 API)                                       │   │
│  │  - GET /v1/users/me: 获取当前用户信息                       │   │
│  └──────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  cloud_storage.py (存储层)                                  │   │
│  │  - 工作空间配置新增 owner 字段                                 │   │
│  │  - list_workspaces 支持 user_id 过滤                        │   │
│  │  - create_workspace 需要 owner 参数                          │   │
│  │  - 存储路径改为 {user_id}/{workspace}/{filename}              │   │
│  │  - 旧工作空间自动迁移(owner 设为 __system__)                │   │
│  └──────────────────────────────────────────────────────────┘   │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  audit_log.py (审计日志)                                    │   │
│  │  - 记录关键操作到 MinIO audit bucket                         │   │
│  │  - 客户端无感知,后端内部记录                                  │   │
│  └──────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

后端改动文件清单

文件 改动类型 改动内容
app/core/config.py 修改 新增 APIKeyConfig 类,SecurityConfig 新增 api_keys 列表
app/core/middleware.py 修改 APIKeyMiddleware 支持多 Key 验证,注入用户信息到 request.state
app/services/cloud_storage.py 修改 工作空间配置新增 owner,存储路径改为用户级隔离
app/api/deps.py 新增 权限检查工具函数
app/api/users.py 新增 GET /v1/users/me 端点
app/api/cloud.py 修改 所有端点添加权限检查,connect 返回用户信息,传递 user_id 给存储层
app/services/audit_log.py 新增 审计日志服务
app/main.py 修改 注册 users router,初始化 AuditLogger
configs/server.yaml 修改 新增多 API Key 配置示例

核心设计逻辑

1. 多 API Key 认证机制

设计思路:每个 API Key 对应一个用户,Key 中携带用户身份和权限信息。服务端通过中间件统一验证,将用户信息注入到请求上下文中,后续 API 处理函数直接从上下文获取。

配置结构

security:
  api_key_enabled: true
  api_keys:
    - key: "user_zhangsan_key"     # API Key 值
      user_id: "zhangsan"          # 用户唯一标识
      name: "张三"                  # 用户显示名称
      permissions: ["read", "write", "delete"]  # 权限列表
      expires_at: "2027-01-01T00:00:00+00:00"   # 可选过期时间

向后兼容:当 api_keys 列表为空但 api_key 不为空时,自动创建一个默认 admin 用户,所有请求都视为 admin。

客户端影响

  • 连接时 POST /v1/cloud/connect 的响应中新增 user 字段
  • 客户端可以解析并显示当前用户信息
  • 旧客户端不解析 user 字段也不会出错

2. 工作空间归属与数据隔离

设计思路:每个工作空间有一个明确的 owner(创建者),工作空间完全私有,只有 owner 能访问。list_workspaces 接口自动按当前用户过滤,只返回该用户自己的工作空间。存储路径从 {workspace}/{filename} 改为 {user_id}/{workspace}/{filename},实现用户级数据隔离。

工作空间配置结构

{
    "workspace": "project-a",
    "owner": "zhangsan",              // 归属者 user_id
    "local_path": "/data/project-a",
    "display_name": "Project A",
    "description": "标注项目 A",
    "created_at": "2026-06-23T10:00:00+00:00",
    "updated_at": "2026-06-23T10:30:00+00:00"
}

过滤逻辑

  • 如果 user_id == owner:返回该工作空间
  • 否则:不返回该工作空间
  • 如果 api_key_enabled=false(兼容模式):返回所有工作空间

旧工作空间迁移:没有 owner 字段的旧工作空间,自动设置 owner = "__system__"

客户端影响

  • 工作空间列表响应新增 owner 字段
  • 工作空间完全私有,列表中只显示当前用户自己的工作空间
  • 无需区分角色(不再有 owner/shared 角色区分)

3. 权限控制机制

设计思路:权限分为两层——基础权限(API Key 配置的 permissions 列表)和工作空间访问权限(是否为 owner)。两层都通过才算有权限。

权限检查流程

请求进入
  │
  ▼
APIKeyMiddleware 验证 Key
  │ 无效 → 401 UNAUTHORIZED
  ▼
注入 user_id / permissions 到 request.state
  │
  ▼
API 处理函数
  │
  ├─ 检查基础权限(permissions 列表是否包含所需权限)
  │   │ 不包含 → 403 FORBIDDEN
  │   ▼
  ├─ 检查工作空间访问权限(是否为 owner)
  │   │ 不是 → 403 WORKSPACE_ACCESS_DENIED
  │   ▼
  └─ 执行业务逻辑

特殊规则

  • admin 权限绕过所有检查
  • api_key_enabled=false 时,跳过所有权限检查(request.state 中没有 user_id
  • 工作空间不存在时,权限检查放行,交给后续业务逻辑返回 NOT_FOUND

各端点权限映射

端点 基础权限 额外检查
POST /v1/cloud/connect
POST /v1/cloud/disconnect
GET /v1/users/me
GET /v1/cloud/workspaces read 按用户过滤
POST /v1/cloud/workspaces write
PUT /v1/cloud/workspaces/{ws} write owner 或 admin
DELETE /v1/cloud/workspaces/{ws} delete owner 或 admin
GET /v1/cloud/workspaces/{ws}/files read 工作空间访问(owner)
POST /v1/cloud/workspaces/{ws}/upload write 工作空间访问(owner)
GET /v1/cloud/workspaces/{ws}/download/{file} read 工作空间访问(owner)
DELETE /v1/cloud/workspaces/{ws}/files/{file} delete 工作空间访问(owner)
GET /v1/cloud/workspaces/{ws}/checksum/{file} read 工作空间访问(owner)
POST /v1/cloud/workspaces/resolve read

客户端影响

  • 所有文件操作端点可能新增 403 错误
  • 客户端需要处理 FORBIDDENWORKSPACE_ACCESS_DENIED 错误码
  • 建议显示友好的权限提示

客户端修改指南

阶段 1:核心适配(必须)

以下修改确保客户端能在新后端下正常工作:

1.1 sync_api.py 修改

连接接口响应解析

# 旧代码
def connect(self, server_url, api_key):
    response = requests.post(f"{server_url}/v1/cloud/connect", headers={"Token": api_key})
    data = response.json()
    if data["success"]:
        self._connected = True
        # 旧代码到此结束

# 新代码
def connect(self, server_url, api_key):
    response = requests.post(f"{server_url}/v1/cloud/connect", headers={"Token": api_key})
    data = response.json()
    if data["success"]:
        self._connected = True
        # 新增:解析用户信息
        user_info = data["data"].get("user", {})
        self._current_user = {
            "user_id": user_info.get("user_id", ""),
            "name": user_info.get("name", ""),
            "permissions": user_info.get("permissions", []),
        }

工作空间列表响应解析

# 旧代码
def list_workspaces(self):
    response = requests.get(f"{self._server_url}/v1/cloud/workspaces", headers=self._headers)
    data = response.json()
    if data["success"]:
        return data["data"]  # 列表中只有 workspace, local_path, display_name 等字段

# 新代码
def list_workspaces(self):
    response = requests.get(f"{self._server_url}/v1/cloud/workspaces", headers=self._headers)
    data = response.json()
    if data["success"]:
        workspaces = data["data"]
        for ws in workspaces:
            # 新增字段:owner
            ws["owner"] = ws.get("owner", "")
        return workspaces

新增用户信息接口

def get_current_user(self):
    """获取当前用户信息。"""
    response = requests.get(f"{self._server_url}/v1/users/me", headers=self._headers)
    data = response.json()
    if data["success"]:
        return data["data"]
    return None
1.2 sync_manager.py 修改
# 新增用户信息保存
class CloudSyncManager:
    def __init__(self):
        self._current_user = None  # 新增

    def connect(self, server_url, api_key):
        # ... 现有连接逻辑 ...
        # 连接成功后保存用户信息
        self._current_user = self._api.get_current_user()
        # 或者从 connect 响应中获取

    @property
    def current_user(self):
        return self._current_user
1.3 cloud_sync_widget.py 修改

显示当前用户

def _update_connection_ui(self):
    """连接成功后更新 UI。"""
    user = self._manager.current_user
    if user:
        # 在标题栏或状态栏显示用户名
        self._user_label.setText(f"用户: {user.get('name', user.get('user_id', ''))}")
        # 可选:显示权限信息
        permissions = user.get("permissions", [])
        self._permissions_label.setText(f"权限: {', '.join(permissions)}")

工作空间列表适配

def _populate_workspace_list(self, workspaces):
    """填充工作空间列表。"""
    self._workspace_combo.clear()
    for ws in workspaces:
        display_name = ws.get("display_name", ws["workspace"])
        owner = ws.get("owner", "")

        # 显示归属信息(可选)
        if owner:
            label = f"{display_name} (归属: {owner})"
        else:
            label = display_name

        self._workspace_combo.addItem(label, ws)

    # 所有工作空间都属于当前用户,删除按钮始终可见
    current_ws = self._get_current_workspace()
    if current_ws:
        self._delete_workspace_btn.setVisible(True)
1.4 错误处理适配
def _handle_error(self, error_response):
    """统一错误处理。"""
    error = error_response.get("error", {})
    code = error.get("code", "")
    message = error.get("message", "")

    if code == "UNAUTHORIZED":
        # API Key 无效,提示重新输入
        self._show_error_dialog("认证失败", "API Key 无效,请重新输入")
        self._disconnect()
    elif code == "API_KEY_EXPIRED":
        self._show_error_dialog("Key 已过期", "API Key 已过期,请联系管理员更新")
        self._disconnect()
    elif code == "FORBIDDEN":
        # 权限不足
        self._show_error_dialog("权限不足", f"您没有执行此操作的权限\n{message}")
    elif code == "WORKSPACE_ACCESS_DENIED":
        # 无权访问工作空间
        self._show_error_dialog(
            "无权访问",
            f"您没有访问此工作空间的权限\n{message}"
        )
    else:
        # 其他错误
        self._show_error_dialog("操作失败", message)

客户端改动清单汇总

文件 优先级 改动内容
sync_api.py 必须 解析 connect 响应中的 user 字段
sync_api.py 必须 解析 workspaces 响应中的 owner 字段
sync_api.py 必须 处理 403 错误码(FORBIDDEN, WORKSPACE_ACCESS_DENIED)
sync_api.py 可选 新增 get_current_user() 方法
sync_manager.py 必须 保存当前用户信息
cloud_sync_widget.py 必须 显示当前用户名
cloud_sync_widget.py 必须 显示工作空间归属者信息(可选)

兼容性说明

场景 客户端行为 服务端行为
旧客户端 + 旧服务端 正常工作 正常
旧客户端 + 新服务端(单 Key) 正常工作 自动注入 admin 用户,权限检查跳过
旧客户端 + 新服务端(多 Key) 正常工作,但看不到用户信息 正常验证,user 字段被旧客户端忽略
新客户端 + 旧服务端 正常工作 user 字段不存在,get() 返回空值
新客户端 + 新服务端 完整功能 完整功能

关键结论:新旧客户端都可以与新旧服务端正常配合工作。新客户端在连接旧服务端时,user 字段不存在但不会报错(使用 get() 安全获取)。旧客户端在连接新服务端时,新增字段被忽略,不影响原有功能。


版本历史

v2 (2026-06-23)

  • 新增多用户支持
  • 新增工作空间归属与数据隔离(存储路径改为 {user_id}/{workspace}/{filename}
  • 新增权限控制(read/write/delete/admin)
  • 新增审计日志
  • 新增 GET /v1/users/me 端点
  • POST /v1/cloud/connect 响应新增 user 字段
  • GET /v1/cloud/workspaces 响应新增 owner 字段
  • 移除分享功能(工作空间完全私有,只有 owner 能访问)

v1 (2026-06-20)

  • 初始版本
  • 基础工作空间管理
  • 文件上传/下载/删除
  • 单 API Key 认证