Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Server 总览

cr4sync serve 是把第三方网盘 → Cloudreve 迁移能力以 HTTP API 形式暴露给多个 Cloudreve 用户的服务模式。仅在编译时启用 server cargo feature 才包含。

设计原则

  1. CLI 模式完全不变:CLI 仍走 ./credential/token.json + ./credential/sources/baidu.json + ./credential/migrate.db + toml [[storage]]
  2. Server 全状态收敛到 ./credential/server.db:所有 user / 凭证 / storage / migrate / audit 都在这一个 sqlite 文件,与 CLI 完全隔离,备份只需一个文件。
  3. cloudreve 身份强隔离(P0 不变量):server 路径上传 cloudreve 必须使用调用方 JWT,严禁读取站长 credential/token.json。静态 grep 守护测试兜底。
  4. 行级隔离:所有 server.db Repo 方法签名首参数必带 user_id,admin 跨用户走专门 *_admin 方法。
  5. admin 自动识别:Cloudreve /user/info 响应的 data.group.name 默认命中 "Admin" / "管理员" 任一即为 admin;可用 [serve.cr4].admin_group 覆盖,moka 缓存 60s。
  6. JWT 不本地验签:cr4sync 不持有 Cloudreve secret,每次 cache miss 走远端 /user/info/{sub} 校验。
  7. 第三方 refresh_token 加密落 server.db:AES-256-GCM 加密, 密钥编译进二进制混淆存储, 不入 config / DB / 日志。站长拿到 DB 只看到密文。
  8. cloudreve refresh_token 仅内存态:随 POST /migrate body 传入,活在 JobTokenState 内存里,job 完成即抛弃,不入 db

路径前缀

server 所有 API 路径前缀固定 /api/v4/cr4sync[serve.cr4].server_api_path 无关——后者是连上游 Cloudreve 用的)。

embed-web 构建下还会在 /extensions/cr4sync 伺服内嵌的前端 SPA(静态资产,不鉴权)。同源部署为 cloudreve 扩展时,nginx 把 /api/v4/cr4sync//extensions/cr4sync 两个 location 反代到 server;详见 部署

API 速览

MethodPath说明鉴权
GET/health健康检查
GET/meta(version / user_id / is_admin / banned)
POST/auth/login账密登录 (独立部署)
POST/auth/login/2fa2FA 验证
GET/auth/captcha/status验证码类型与配置
GET/auth/captcha图形验证码图片 + ticket
POST/auth/token/refresh刷新 token
POST/auth/qr/create创建扫码会话
GET/auth/qr/status/:id扫码状态轮询
GET/auth/qr/result/:id取扫码结果
GET/sources支持的 driver + 用户登录态
GET/POST/PUT/DELETE/source/:driver/storage[/{name}]storage CRUD, driver ∈ baidu/onedrive/aliyun/pikpak
POST/source/baidu/login-session百度 OAuth 启动 (含 oob 授权 URL)
POST/source/baidu/login-submit[?code=]百度 OAuth 提交 code 或 refresh_token
POST/source/onedrive/login-sessionOneDrive OAuth 启动
POST/source/onedrive/login-submit[?code=]OneDrive OAuth 提交 code 或 refresh_token
POST/source/aliyun/login-session阿里云盘 OAuth 启动
POST/source/aliyun/login-submit[?code=]阿里云盘 OAuth 提交 code 或 refresh_token
POST/source/:driver/credentialS3/OSS/COS 直接凭证 upsert(非 OAuth,driver ∈ s3/oss/cos)
POST/source/pikpak/credentialPikPak 账密登录(非 OAuth,直接提交 email/password)
GET/browse/storage/{name}?type=&path=&limit=&offset=storage 双端浏览 (源+目标), 分页
GET/browse/storage?is_create_storage=true&type=&path=&limit=&offset=新建 storage 浏览 (无 storage name)
GET/source/baidu/info百度网盘用户信息 + 容量
GET/source/cloudreve/infocloudreve 源用户信息 + 容量
GET/POST/PUT/DELETE/proxies[/{name}]代理 CRUD (列表/创建/更新/删除)
POST/migrate异步创建 migrate job
GET/migrate/jobs枚举当前用户 job
GET/migrate/jobs/{job_id}查询 job 状态
GET/migrate/jobs/{job_id}/tasks分页枚举该 job 的 task
GET/migrate/jobs/{job_id}/tasks/{task_id}查询该 job 下单 task
GET/migrate/sseSSE 进度推送
POST/migrate/jobs/{job_id}/cancel取消 job
GET/admin/users[/...]admin 跨用户查询✓ admin
DELETE/admin/users/{user_id}级联清用户 server.db 痕迹✓ admin
GET/POST/admin/jobs[/...]admin 持久化 job 看板✓ admin
GET/admin/audit审计日志查询✓ admin
GET/admin/stats全局统计✓ admin
GET/admin/doc/book[/*]内嵌 mdbook 文档 (仅 server/*.html 校验权限)

详见 API 接口 各页。

模块布局

cr4sync/src/server/
├── mod.rs                            # serve(cfg) 入口
├── state.rs                          # AppState (Arc bundle)
├── error.rs / response.rs            # ApiError + Resp<T> envelope
├── db/{mod,user_repo,source_cred_repo,storage_repo,migrate_repo,audit_repo,proxy_repo}.rs
├── middleware/{request_id,auth,require_admin,audit,access_log}.rs
├── auth/{jwt,validator}.rs           # base64 JWT 解 + moka cache + lazy upsert
├── providers/token.rs                # TokenProvider + JobTokenState
├── jobs/{manager,migrate_job,event}.rs
├── sse/stream.rs                     # broadcast → SSE 按 user_id 过滤
├── token_isolation_guard.rs          # #[cfg(test)] 静态 grep 守护 (P0 不变量)
├── routes/{meta,sources,storage,login_baidu,login_onedrive,login_aliyun,login_pikpak,browse,migrate,admin,proxy}.rs

源端 client 模块布局

cr4sync/src/sources/
├── mod.rs                    # CloudSource trait
├── local.rs                  # 本地 fs 扫描
├── baidu_pan/*               # 百度网盘 (OAuth)
├── onedrive/*                # OneDrive (OAuth)
├── aliyun/*                  # 阿里云盘 (OAuth)
├── proxy.rs                  # 代理 reqwest client 构造 helper (build_proxied_http_client)
├── s3/{mod,client,config,fs,download}.rs   # S3 基底 (aws-sdk-s3)
├── oss/mod.rs                # OSS 薄包装 (复用 S3Client)
└── cos/mod.rs                # COS 薄包装 (复用 S3Client)
	└── pikpak/{mod,api,auth,fs,download}.rs   # PikPak (账密登录, 非 OAuth)

与 CLI 的交叉

  • 共享 [serve.cr4] 段连 Cloudreve 上游
  • 共享 commands/migrate/{pipeline.rs}(通过 MigrateProgressSink trait 抽象),CLI 实现 IndicatifSink,server 实现 BroadcastSink
  • 共享 MigrateTaskStore trait,CLI 实现是 MigrateDb(migrate.db),server 实现是 user-scoped 的 MigrateRepo(server.db)
  • 共享 sources/baidu_pan/*sources/onedrive/*sources/aliyun/*sources/s3/*sources/oss/*sources/cos/*sources/pikpak/* 第三方网盘/对象存储客户端
  • 共享 sources/proxy.rs 代理 client 构造 helper:CLI 从 [[proxy]] 配置段加载,server 从 proxy 表加载。代理在 source_credential 级(driver 登录时绑定),migrate 时复用 source_credential 的代理。

与 CLI 的隔离

  • 不读 token.json / sources/baidu.json(及同目录的 onedrive/aliyun 凭证文件) / migrate.db
  • 不调 commands::prepare_session / commands::prepare_provider
  • 不调 auth::token_store::default_path

静态 grep 守护测试 server::token_isolation_guardcargo test --features server 时扫描 server/**/*.rs,命中上述任一禁字立即失败。