Files
note-manager/API.md
T
Your Name 74fa759274 feat: 云笔记增强 - 安全加固 + 回收站/版本历史/分享/批量导出 + 前端优化
- 安全: 认证改随机token会话(弃固定cookie), 笔记密码SHA256升级为bcrypt(自动迁移),
  堵住GET /api/notes/:id泄露带密码笔记, CORS收紧+SameSite防CSRF, 上传图片内容嗅探
- 回收站: 软删除(deleted_at), 列表/恢复/彻底删除/清空, 目录子树连删连恢复
- 版本历史: note_versions表存快照, 每次保存自动留档, 支持查看/回滚
- 分享: 生成随机token分享链接, 支持过期时间, 公开阅读页share.html
- 批量导出: 全部笔记打包zip(按目录结构+front matter)
- 前端: 深色模式, Mermaid图表, 待办清单checkbox, 字数统计;
  后台新增回收站/历史/分享面板和批量导出按钮
- 新增deploy/note-manager.service systemd单元与smoke_test.py
2026-08-11 11:21:29 +08:00

659 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 云笔记 API 文档
## 基础信息
- **Base URL**`http://localhost:8080/api`
- **认证方式**:Cookie(后台管理接口需要)
- **默认密码**`admin123`
---
## 公开接口
公开接口无需认证即可访问(只读)。
### 1. 获取笔记列表
获取分页的笔记列表。
**请求**
```
GET /api/notes
```
**Query 参数**
| 参数 | 类型 | 必填 | 说明 | 默认值 |
|------|------|------|------|--------|
| page | int | 否 | 页码 | 1 |
| page_size | int | 否 | 每页数量 | 20 |
| category | string | 否 | 按分类筛选 | - |
| tag | string | 否 | 按标签筛选 | - |
| pinned | bool | 否 | 只看置顶 | - |
| favorite | bool | 否 | 只看收藏 | - |
| parent_id | int | 否 | 按父目录筛选 | - |
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": {
"items": [
{
"id": 1,
"title": "Go 语言教程",
"category": "技术",
"tags": "[\"Go\",\"编程\"]",
"is_pinned": true,
"is_favorite": false,
"is_folder": false,
"parent_id": 0,
"sort_order": 0,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"total": 50,
"page": 1,
"page_size": 20,
"total_pages": 3
}
}
```
---
### 2. 获取单条笔记
根据 ID 获取笔记详情。
**请求**
```
GET /api/notes/:id
```
**路径参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| id | int | 笔记 ID |
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": {
"id": 1,
"title": "Go 语言教程",
"content": "# Go 语言\\n\\nGo 是一门简洁高效的编程语言。",
"category": "技术",
"tags": "[\"Go\",\"编程\"]",
"is_pinned": true,
"is_favorite": false,
"is_folder": false,
"parent_id": 0,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
```
---
### 3. 搜索笔记
搜索标题和内容。
**请求**
```
GET /api/notes/search
```
**Query 参数**
| 参数 | 类型 | 必填 | 说明 | 默认值 |
|------|------|------|------|--------|
| q | string | 是 | 搜索关键词 | - |
| page | int | 否 | 页码 | 1 |
| page_size | int | 否 | 每页数量 | 20 |
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": {
"items": [...],
"total": 5,
"page": 1,
"page_size": 20,
"total_pages": 1
}
}
```
---
### 4. 获取分类列表
获取所有分类。
**请求**
```
GET /api/categories
```
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": ["技术", "生活", "工作", "随笔"]
}
```
---
### 5. 获取标签列表
获取所有标签。
**请求**
```
GET /api/tags
```
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": ["Go", "Python", "JavaScript", "编程", "笔记"]
}
```
---
### 6. 获取树形结构
获取目录树形结构(包含目录和笔记)。
**请求**
```
GET /api/tree
```
**响应示例**
```json
{
"code": 0,
"message": "success",
"data": [
{
"id": 1,
"title": "技术文档",
"is_folder": true,
"children": [
{
"id": 2,
"title": "Go 语言教程",
"is_folder": false
}
]
},
{
"id": 3,
"title": "生活随笔",
"is_folder": false
}
]
}
```
---
## 管理接口
管理接口需要先登录,获取 Cookie 认证。
### 7. 登录
**请求**
```
POST /admin/login
```
**Body 参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| password | string | 是 | 管理员密码 |
**响应示例**
```json
{
"code": 0,
"message": "登录成功"
}
```
---
### 8. 登出
**请求**
```
POST /admin/logout
```
**响应示例**
```json
{
"code": 0,
"message": "已退出登录"
}
```
---
### 9. 检查认证状态
**请求**
```
GET /admin/auth
```
**响应示例**
```json
{
"authenticated": true
}
```
---
### 10. 创建笔记/目录
**请求**
```
POST /api/notes
```
**Body 参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| title | string | 是 | 标题 |
| content | string | 否 | 内容(Markdown |
| category | string | 否 | 分类 |
| tags | string | string | 标签(JSON 数组格式) |
| is_folder | bool | 否 | 是否为文件夹 |
| is_pinned | bool | 否 | 是否置顶 |
| is_favorite | bool | 否 | 是否收藏 |
| parent_id | int | 否 | 父目录 ID |
| sort_order | int | 否 | 排序顺序 |
**请求示例**
```json
{
"title": "新建笔记",
"content": "# 我的笔记\\n\\n这是笔记内容",
"category": "技术",
"tags": "[\"笔记\",\"教程\"]",
"is_folder": false
}
```
**响应示例**
```json
{
"code": 0,
"message": "笔记创建成功",
"data": {
"id": 10
}
}
```
---
### 11. 更新笔记/目录
**请求**
```
PUT /api/notes/:id
```
**Body 参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| title | string | 否 | 标题 |
| content | string | 否 | 内容(Markdown |
| category | string | 否 | 分类 |
| tags | string | 否 | 标签 |
| is_pinned | bool | 否 | 是否置顶 |
| is_favorite | bool | 否 | 是否收藏 |
| parent_id | int | 否 | 父目录 ID |
| sort_order | int | 否 | 排序顺序 |
**响应示例**
```json
{
"code": 0,
"message": "笔记更新成功"
}
```
---
### 12. 删除笔记/目录
**请求**
```
DELETE /api/notes/:id
```
**说明**:删除目录时会同时删除该目录下的所有子项。
**响应示例**
```json
{
"code": 0,
"message": "笔记删除成功"
}
```
---
## 响应状态码
| code | 说明 |
|------|------|
| 0 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未授权(需要登录) |
| 404 | 笔记不存在 |
| 500 | 服务器内部错误 |
---
## 密码保护笔记接口
### 访问密码保护的笔记
**请求**
```
POST /api/notes/:id/access
```
**Body 参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| password | string | 是 | 笔记访问密码 |
**响应示例**
```json
{
"code": 0,
"message": "访问成功",
"data": {
"id": 1,
"title": "受保护的笔记",
"content": "# 笔记内容..."
}
}
```
---
## 图片上传接口
### 上传图片
**请求**
```
POST /admin/api/upload
```
**说明**:需要登录认证。仅支持 jpg、png、gif、webp、bmp 格式,最大 5MB。
**Form 参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| image | file | 是 | 图片文件 |
**响应示例**
```json
{
"code": 0,
"message": "上传成功",
"data": {
"url": "/uploads/1234567890_abc123.png"
}
}
```
**图片访问**:上传后的图片通过 `/uploads/文件名` 访问。
---
## 导入导出接口
### 导出笔记为 Markdown
**请求**
```
GET /admin/api/export/:id
```
**说明**:需要登录认证。导出的文件包含 YAML front matter。
**响应**:下载 `.md` 文件,文件名以笔记标题命名。
---
### 导入 Markdown 文件
**请求**
```
POST /admin/api/import
```
**说明**:需要登录认证。仅支持 `.md` 文件。
**Form 参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| file | file | 是 | Markdown 文件 |
**响应示例**
```json
{
"code": 0,
"message": "导入成功",
"data": {
"id": 15,
"title": "导入的笔记标题"
}
}
```
---
## 错误响应示例
```json
{
"code": 401,
"message": "请先登录后台管理"
}
```
---
## 使用示例
### cURL
```bash
# 登录
curl -X POST http://localhost:8080/admin/login \
-d "password=admin123" \
-c cookies.txt
# 获取笔记列表
curl http://localhost:8080/api/notes
# 搜索笔记
curl "http://localhost:8080/api/notes/search?q=Go"
# 创建笔记(需要认证)
curl -X POST http://localhost:8080/api/notes \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{"title":"新笔记","content":"# 标题\\n\\n内容"}'
# 更新笔记(需要认证)
curl -X PUT http://localhost:8080/api/notes/1 \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{"title":"更新后的标题"}'
# 删除笔记(需要认证)
curl -X DELETE http://localhost:8080/api/notes/1 -b cookies.txt
```
### JavaScript (Fetch API)
```javascript
// 登录
await fetch('/admin/login', {
method: 'POST',
body: new URLSearchParams({ password: 'admin123' }),
credentials: 'include'
});
// 获取笔记列表
const res = await fetch('/api/notes');
const data = await res.json();
// 创建笔记
await fetch('/api/notes', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: '新笔记', content: '# 内容' }),
credentials: 'include'
});
```
---
# 新增功能 APIv2
## 管理接口认证(安全优化)
后台管理写操作(创建/更新/删除/回收站/版本/分享/导入导出/上传)统一走 `/admin/api`
需登录后携带服务端会话 cookie(随机 token,非固定字符串)。未登录返回 401。
## 安全策略调整
### 公开接口 `GET /api/notes/:id`
仅返回 **公开且未设置密码** 的笔记完整内容。带密码或未公开的笔记返回 403(需走密码验证接口),
防止绕过密码保护直接读取内容。
## 回收站(软删除)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/admin/api/trash` | 回收站列表(含已删除的目录和笔记) |
| POST | `/admin/api/restore/:id` | 恢复笔记/目录(目录连子树一起恢复) |
| POST | `/admin/api/purge/:id` | 彻底删除(不可恢复,含版本历史) |
| POST | `/admin/api/empty-trash` | 清空回收站 |
删除笔记 `DELETE /admin/api/notes/:id` 现为软删除(进入回收站),目录删除会连带软删除所有子项。
## 版本历史
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/admin/api/notes/:id/versions` | 获取笔记全部历史版本 |
| POST | `/admin/api/notes/:id/restore-version` | 恢复指定版本(form: `version_id` |
每次保存(标题或内容变化)自动生成快照。
## 分享链接
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/admin/api/notes/:id/share` | 创建分享(form: `expire_hours`0=永久) |
| POST | `/admin/api/notes/:id/revoke-share` | 撤销分享 |
| GET | `/api/share/:token` | 公开获取分享笔记 JSON(有密码需带 `?password=` |
| GET | `/share/:token` | 分享阅读页(HTML) |
## 批量导出
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/admin/api/export-all` | 全部笔记导出为 zip(按目录结构 + YAML front matter |
## 图片上传(安全增强)
上传会做**内容嗅探**(magic bytes 校验),不仅检查扩展名。伪装成图片的脚本会被拒绝。
## 后台管理笔记接口
管理端读取/写笔记统一走 `/admin/api/notes`(可访问私有、带密码笔记):
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/admin/api/notes` | 创建 |
| GET | `/admin/api/notes/:id` | 详情(完整内容) |
| PUT | `/admin/api/notes/:id` | 更新 |
| DELETE | `/admin/api/notes/:id` | 软删除 |
## 前端新增功能
- **深色模式**:前台/后台均可切换(🌙/☀️ 按钮),偏好存 localStorage
- **Mermaid 图表**:前台 Markdown 中 ` ```mermaid ` 代码块渲染为流程图/时序图等
- **待办清单**:前台渲染 `- [ ]` / `- [x]` 可勾选清单
- **字数统计**:前台笔记详情显示字数与预估阅读时长
- **回收站/版本历史/分享**:后台工具栏按钮 + 面板