Files
ChuBlog/docs/publishing.md
T

107 lines
5.9 KiB
Markdown
Raw Normal View History

2026-10-16 18:09:11 +08:00
# 账户授权与文章发布
[返回项目首页](../README.md)
## 用户与发布授权
完整接口见 [API 文档](API.md)。
1. 注册:`POST /api/auth/register`,正文 `{ "username": "alice", "password": "至少12字节的口令" }`。默认角色 `reader`,绝不接受客户端指定角色。`ALLOW_REGISTRATION=false` 可关闭注册。
2. 登录:`POST /api/auth/login`,相同字段。浏览器保存 HttpOnly Cookie;返回 `csrf`。所有修改请求必须携带站点 `Origin` 和 `X-CSRF-Token`。
3. 本地生成 `ssh-keygen -t ed25519` 或 `ssh-keygen -t rsa -b 3072`;登录后 `PUT /api/account/ssh-key` 提交 `{ "public_key": "ssh-ed25519 AAAA..." }`,只交公钥。RSA 使用标准 `ssh-rsa AAAA...` 公钥文本,支持 2048–8192 位;实际认证使用 RSA/SHA-256 或 RSA/SHA-512,不启用旧的 SHA-1 签名。见 [OpenSSH 说明](https://www.openssh.com/txt/release-8.8)。
4. 管理员登录后调用 `PATCH /api/admin/users/alice`,正文 `{ "enabled": true, "role": "publisher" }`。服务器按公钥绑定的用户分配独立仓库。
5. 此时 SSH 才接受该用户的密钥;`reader`、停用用户、未绑密钥的用户均不能访问 Git。管理员也需登记公钥才能发布。旧 `prefixes` 字段仅为兼容保留,不再用于文章隔离。
- 授权与密钥独立:知道服务器地址、有网站账户、上传了公钥都不足以推送。
- 设回 `reader` 或 `enabled:false` 会撤回发布授权,并使现有网站会话失效。
- 禁止管理员停用自己或取消自己的管理角色。
## 本地 Git 工作流
- 先通过可信渠道核对服务器 Ed25519 主机密钥指纹;不要禁用主机密钥检查。
- 主机密钥保存在独立持久卷,重建容器不会更换。
- 所有发布者使用同一个 OS 账户 `git`,身份由对应公钥的强制命令绑定,不由 Git author/email 决定。
```sh
# ~/.ssh/config
Host chublog
HostName blog.example.com
Port 2222
User git
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
# 无论作者是谁,别名都是 content.git;服务端按认证身份映射个人仓库。
# 首次 clone 自动创建服务器裸仓库,作者无须自己创建裸仓库。
git clone chublog:content.git my-articles
cd my-articles
# 仓库已有内容时,每轮编辑前先 git pull --ff-only。
# 创建 index.txt 和正文,格式见下文。
git add index.txt posts/first
git commit -m 'Publish first article'
git push -u origin main
```
## 文章目录与清单
仓库结构示例:
```text
index.txt
posts/
└── first/
├── article.md
└── cover.png
```
`index.txt` 为 UTF-8 三列文本,以空格或 Tab 分隔,无表头,允许空行:
```text
first posts/first article.md
notes posts/my-notes notes.markdown
```
- 三列依次为**文章 ID、相对文件夹、正文文件名**。
- ID 在作者内唯一,支持 1–40 位小写字母、数字及中间短横线,另须避开保留名称。
- 目录必须是 `posts/<目录名>`,目录名遵循 slug 规则,最多 80 字节;文件名只允许 ASCII 字母、数字、短横线、下划线与点,不能以点开头或含 `..`。
- 同一目录不能重复登记;正文可以任意命名,扩展名为 `.md`、`.markdown` 或 `.txt`。
- 索引所指目录和正文必须存在,路径穿越和子目录正文被拒绝。
- 索引上限 64 KiB、1000 项。
## 正文与图片
- 正文沿用 YAML Frontmatter(参考[正文样例](../content/posts/welcome/index.md)),包含 `title/date/updated/status/tags/description`;`slug` 可省略,如填写则必须等于索引 ID。
- `.txt` 正文也需要 Frontmatter,API 通过 `format: text` 表明正文应作为纯文本展示;其他正文为 `format: markdown`。
- 图片置于同一目录,通过 `![说明](cover.png)` 引用。
## 新增、修改与撤回
| 作者操作 | 系统处理 |
| --- | --- |
| 新建正文并在索引新增一行 | 校验后导入文章,在 ChuSQL 创建作者、ID、正文路径、状态等元信息 |
| 修改正文或索引中的目录/文件名,保留 ID | 更新同一文章;站内 ID 不随目录移动而变化 |
| 删除索引中的一行 | 移除当前阅读内容、图片入口及对应数据库元信息,无需先删除本地正文 |
| 把索引清空 | 移除该作者所有当前文章,不影响其他作者 |
- 未被索引选中的正文及目录视为无效内容,不导入阅读快照或数据库;图片只有被选中正文引用才作为公开资源导入;仍计算仓库容量并执行安全校验。
- 删除正文但保留其索引项属于错误,整次推送会被拒绝。
- `status: draft` 可保留登记但不公开;物理删除文件和撤回文章均不会擦除 Git 历史。
## 提交与并发限制
- MVP 每次只接受**一个直接继承个人远端 main 的提交**,首次仅允许一个根提交。
- 禁止 merge、force push、删除 main、标签及其他分支;多次本地提交应先整理为一次提交,再变基到最新远端。
- 同一作者在多台电脑操作仍需处理并发冲突,不同作者互不争用同一个仓库锁。
## 作者隔离与文章地址
- 站内文章 ID 为 `作者名~文章ID`,例如 Alice 的 `first` 对应 `/api/posts/alice~first`;不同作者可以使用相同的本地 ID。
- 服务端分别保存每位作者的 Git 对象与历史,SSH 不能指定别人的仓库路径;作者无法通过 clone 或按提交哈希 fetch 读取其他作者草稿。
- 作者自己已克隆的历史仍可在本地保留,不能靠撤回收回副本。
## 发布状态
- API 自动同步,一般约 2 秒,数据库重建、失败重试或较多作者可能延迟。
- `GET /api/admin/status` 的 `commit` 是作者提交映射的集合摘要,不是任一作者 Git 提交;`indexed_commit` 表示数据库已同步的集合版本。
- Git 接受表示接收校验完成,不保证数据库已同步。
- 当前不做站长内容审核,审核计划见 [TODO](../TODO.md)。