Files
WebDAV/docs/REQUIREMENTS.md

4.5 KiB
Raw Permalink Blame History

davbox · 需求文档

0. 定位

用户需要一个概念只有两个的自建 WebDAV 服务:

  • admin:管理账号(新增 / 删除 / 改密码 / 看目录与用量)
  • client:账号登录后管理自己的文件
  • 主要消费者是 App:思源笔记、Joplin 等通过 WebDAV 同步

设计分工(关键):WebDAV 协议不自研(底盘用 Go 官方 golang.org/x/net/webdav), 产品层 100% 自研(账号模型、目录隔离、admin 页、client 页)。

1. 阶段一:底盘(本次委托范围)

做:一个 Go 二进制,读账号配置,按账号隔离地提供完整 WebDAV 服务。 不做(留给阶段二/三):admin 页、client 页、配额、HTTPS、SSO、日志文件、数据库。

阶段一唯一目的:证明底盘与隔离是可信的。

硬性边界(违反任何一条即视为任务失败)

  • 绝不 执行 systemctl / service 任何操作
  • 绝不 执行 pkill / killall / kill 任何已存在的进程
  • 绝不 触碰任何已在运行的端口(80 / 443 等)
  • 绝不 修改仓库之外的任何系统配置(服务、容器、nginx、cron、其他项目的文件)
  • 不新增第三方依赖:只允许 golang.org/x/net/webdav
  • 只准修改本仓库内的文件
  • 服务只准监听 127.0.0.1:18900
  • 测试进程自己起自己收,按 PID 收尾

交付物

./
├── cmd/davbox/main.go        # 入口
├── internal/account/         # 账号加载 + Basic 认证 + 路由
├── internal/fs/              # 按账号 chroot 的文件系统封装
├── go.mod                    # module davbox
├── accounts.json             # 示例:app1 / app2
└── davbox                    # go build 产物

功能要求

  1. 配置:accounts.json 为数组,每项 { "user": "app1", "pass": "...", "root": "/abs/path", "readonly": false }
  2. 认证:HTTP Basic,口令用 crypto/subtle 常量时间比较; 未认证/失败 → 401,必须带 WWW-Authenticate: Basic realm="davbox"(客户端靠它重试)
  3. URL 空间:/<user>/... → 剥离前缀映射到该账号 root 下的相对路径 例:账号 app1(root=/srv/dav/app1)收 PUT /app1/notes/a.txt → 落盘 /srv/dav/app1/notes/a.txt
  4. 越权必须失败:访问他人前缀、../、%2e%2e、双重编码、绝对路径逃逸 → 401/403/404 之一,绝不允许成功
  5. 只读账号:PUT / DELETE / MKCOL / MOVE / COPY / PROPPATCH → 403;GET / PROPFIND 正常
  6. 六个动词可用:GET / PUT / DELETE / MKCOL / MOVE / PROPFIND(PROPFIND 正确处理 Depth: 0 与 Depth: 1 并返回合法 207 Multi-Status)
  7. 启动参数:-addr 127.0.0.1:18900 -c accounts.json;日志到 stdout,不写文件
  8. root 不存在时自动 MkdirAll
  9. Basic 认证通过后的请求不得把口令写进日志

验收标准(逐条实测,不看自述)

# 项目 通过条件
1 六动词 GET / PUT / DELETE / MKCOL / MOVE / PROPFIND 全部返回正确状态码
2 跨账号读 app1 读 app2 目录 → 401/403/404
3 跨账号写 app1 写 app2 目录 → 401/403/404
4 ../ 逃逸 错误码,且磁盘不产生越狱文件
5 %2e%2e 逃逸 同上
6 落盘位置 app1 写的内容只在 app1 的 root 里
7 未认证 401 且响应头含 WWW-Authenticate
8 只读账号 写 403 / 读 200-207
9 空闲内存 RSS < 30 MB
10 收尾 只监听 127.0.0.1:18900;按 PID 可干净停掉
11 合规(加分项) 若能跑通 litmus 基础集更好(internal/litmus_test_server.go 有现成入口)

2. 阶段二:admin 页 + client 页(下一轮委托)

  • admin 页(登录:独立管理员账号)
    • 列表:应用名 / 目录 / 已用空间 / 只读开关 / 最近活动
    • 操作:新增应用(自动生成强口令 + 建目录)、改密码、改只读、停用、删除(目录保留)
    • 每行一个「复制连接信息」按钮:地址 + 用户名 + 口令,一次复制走
  • client 页(登录:应用账号)
    • 浏览 / 上传 / 下载 / 删除 / 新建文件夹 / 重命名;面包屑导航;移动端可用(不隐藏导航)
  • 视觉:Swiss 极简;文案中文、克制,不放技术说明

3. 阶段三(可选,等你点名)

配额限制、用量趋势、分享链接(走带 token 的公开链接那套口径)、审计日志页