first commit

This commit is contained in:
qwq
2026-07-24 11:34:38 +08:00
commit 94f4f174f4
26 changed files with 2544 additions and 0 deletions
+316
View File
@@ -0,0 +1,316 @@
# 文件传输自动化系统
飞书审批驱动的企业文件传输与权限自动化管理系统。
## 系统架构
```
飞书审批事件 ──→ Express 服务 ──→ 群晖 NAS API(文件复制)
│ ──→ JumpServer API(远程命令)
│ ──→ Nextcloud API(文件共享)
├── SQLite(操作日志)
├── 管理后台(Web UI)
└── 飞书机器人(告警通知)
```
## 快速开始
### 1. 环境要求
- Node.js >= 18
- 可访问群晖 NAS、JumpServer、Nextcloud 的网络
- 公网 IP 或域名(用于飞书事件回调)
### 2. 安装部署
```bash
# 克隆项目
git clone <your-repo> file-transfer-automation
cd file-transfer-automation
# 安装依赖
npm install
# 复制配置文件并填写
cp .env.example .env
# 编辑 .env 填入实际的 API 密钥和地址
# 启动
npm start
```
或使用 Docker
```bash
cp .env.example .env
# 编辑 .env
docker-compose up -d
```
### 3. 验证
访问 `http://你的服务器IP:3000/health` 确认服务正常。
---
## 飞书应用创建指南(从零开始)
### 第一步:创建企业自建应用
1. 打开 [飞书开放平台](https://open.feishu.cn/app),用管理员账号登录
2. 点击「创建企业自建应用」
3. 填写应用名称(如"文件传输自动化")和描述
4. 创建后进入应用详情页,记录 **App ID****App Secret**
### 第二步:配置权限
在应用详情页 →「权限管理」中,搜索并开通以下权限:
| 权限名称 | 权限标识 | 用途 |
|---------|---------|------|
| 获取审批实例详情 | approval:instance:read | 读取审批表单内容 |
| 同意审批 | approval:instance:approve | 自动提交审批意见 |
| 查看审批定义 | approval:approval:read | 获取审批配置 |
| 添加审批评论 | approval:instance:comment | 添加审批评论 |
### 第三步:配置事件订阅
1. 进入应用详情页 →「事件订阅」
2. 请求地址填写:`http://你的公网IP:3000/api/feishu/event`
3. 系统会发送验证请求,确保服务已启动
4. 添加事件:搜索「审批实例状态变更」(`approval_instance`)
5. 记录 **Verification Token**(页面顶部显示)
> 注意:飞书要求回调地址必须是公网可访问的 HTTP/HTTPS 地址。
### 第四步:发布应用
1. 进入「版本管理与发布」
2. 创建版本 → 提交审核
3. 管理员在飞书管理后台审核通过
### 第五步:配置审批流程
在飞书管理后台 → 审批管理中:
1. 创建/编辑三个审批表单(文件传入、文件传出、红区组权限)
2. 在审批流程设计中,添加「机器人审批」节点(让应用自动处理)
3. 记录每个审批的 **审批定义 Code**(在审批设置页面的 URL 中可以看到)
### 第六步:配置告警机器人
1. 在飞书中创建一个告警通知群
2. 群设置 → 群机器人 → 添加机器人 → 自定义机器人
3. 记录 Webhook 地址,填入 `.env``FEISHU_ALERT_WEBHOOK`
---
## API 接入说明
### 群晖 NAS (Synology DSM)
**前提条件:**
- DSM 6.0+ 或 7.0+
- 开启 FileStation API(默认开启)
- 准备一个有文件管理权限的账号
**获取配置:**
- `SYNOLOGY_HOST`: NAS 地址,如 `https://192.168.1.100:5001`
- 使用自签证书时设 `SYNOLOGY_SKIP_TLS=true`
- 确保运行本服务的服务器能访问 NAS 的 5001 端口
**验证连接:**
```bash
curl -k "https://NAS_IP:5001/webapi/auth.cgi?api=SYNO.API.Auth&version=6&method=login&account=admin&passwd=xxx&format=sid"
```
### JumpServer 3.x
**前提条件:**
- JumpServer 3.x 版本
- 有 API Key 权限(在 JumpServer 控制台 → 系统设置 → API Key 中创建)
- ic1 服务器已作为资产录入 JumpServer
**获取配置:**
- `JUMPSERVER_HOST`: JumpServer 地址
- `JUMPSERVER_KEY_ID` / `JUMPSERVER_KEY_SECRET`: API Key
- `JUMPSERVER_ASSET_IC1`: 在 JumpServer 控制台 → 资产管理 → 找到 ic1 → URL 中的 UUID
- `JUMPSERVER_SYSTEM_USER`: 连接 ic1 使用的系统用户(如 root)
**验证连接:**
```bash
curl -H "Authorization: Token KEY_ID:KEY_SECRET" https://JUMPSERVER_HOST/api/v1/assets/hosts/
```
### Nextcloud
**前提条件:**
- Nextcloud 已启用 WebDAV(默认启用)
- 准备一个有文件管理权限的账号
- 如需共享功能,确保 files_sharing 应用已启用
**获取配置:**
- `NEXTCLOUD_HOST`: Nextcloud 地址
- 用户名/密码用于 WebDAV 认证
**验证连接:**
```bash
curl -u user:pass https://NEXTCLOUD_HOST/remote.php/dav/files/user/ -X PROPFIND
```
---
## 部署方案
### 方案 A:公网 IP 服务器(推荐)
本服务非常轻量(Node.js + SQLite,内存占用约 50-100MB),适合部署在有公网 IP 的服务器上。
```bash
# 使用 Docker 部署
docker-compose up -d
# 或直接运行
npm install --production
NODE_ENV=production node src/index.js
```
配合 Nginx 反向代理(可选,用于 HTTPS):
```nginx
server {
listen 443 ssl;
server_name automation.yourcompany.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
```
### 方案 B:无公网 IP 的内网服务器
如果服务必须部署在内网(比如需要直接访问群晖 NAS),有两种方式接收飞书事件:
**方式 1:内网穿透(frp**
在公网服务器上部署 frps,内网服务器部署 frpc:
```ini
# frpc.ini(内网服务器)
[server]
server_addr = 公网服务器IP
server_port = 7000
[file-automation]
type = http
local_port = 3000
custom_domains = automation.yourcompany.com
```
飞书事件回调地址填:`http://automation.yourcompany.com/api/feishu/event`
**方式 2:飞书长连接模式(推荐)**
飞书支持 WebSocket 长连接模式,不需要公网回调地址。修改事件接收方式:
```javascript
// 使用 @larksuiteoapi/node-sdk 的长连接模式
const { Client, EventDispatcher } = require('@larksuiteoapi/node-sdk');
const client = new Client({ appId, appSecret });
const wsClient = client.event.wsClient; // WebSocket 长连接
wsClient.start(); // 主动连接飞书,无需公网IP
```
> 长连接模式需要安装 `@larksuiteoapi/node-sdk` 包,适合内网部署场景。
### 方案 C:混合部署
公网服务器放一个轻量转发层(只接收飞书回调),内网服务器跑主业务逻辑:
```
飞书 ──→ 公网服务器(转发) ──→ 内网服务器(业务处理) ──→ 群晖/JumpServer/Nextcloud
```
---
## 审批表单字段设计
为了让自动化系统正确解析,审批表单字段名需要与代码中的映射一致:
### 文件传入审批
| 字段名 | 类型 | 说明 |
|--------|------|------|
| 申请人 | 文本/人员 | 申请人姓名 |
| 文件名称 | 文本 | 要传入的文件名 |
### 文件传出审批
| 字段名 | 类型 | 说明 |
|--------|------|------|
| 申请人 | 文本/人员 | 申请人姓名 |
| 文件路径 | 文本 | 文件在服务器上的完整路径 |
| 传出目的 | 单选 | 内部使用 / 客户发布 |
| 客户名缩写 | 文本 | 仅客户发布时填写 |
| 文件过期日期 | 日期 | 仅客户发布时填写 |
### 红区组权限审批
| 字段名 | 类型 | 说明 |
|--------|------|------|
| 待添加人员 | 文本/人员 | 人员姓名 |
| 申请类型 | 单选 | 添加至已有group / 新建group |
| group名称 | 文本 | Linux 组名 |
> 如果你的表单字段名不同,修改 `src/routes/feishu-event.js` 中的字段映射即可。
---
## 管理后台
访问 `http://服务器IP:3000/admin`,使用 `.env` 中配置的 `ADMIN_PASSWORD` 登录。
功能包括:
- 仪表盘:今日操作统计、系统状态
- 操作日志:按类型/状态/时间/关键词筛选,保留30天
- 预设命令:管理可在 ic1 上执行的预设命令
- API配置:动态管理配置项
---
## 安全机制
1. **白名单目录**:所有文件操作路径必须在白名单内(`/IN_R`, `/OUT_R`, `/OUT`, `/wingsemi`, `/WCPS-Files`, `/OUT-RED`
2. **路径穿越防护**:自动规范化路径,阻止 `../` 攻击
3. **命令注入防护**:禁止 `;``$(`、反引号、`rm -rf` 等危险模式
4. **审批绑定**:每次操作记录审批单号、申请人、时间,保留一个月
5. **防重复处理**:同一审批实例不会重复执行
6. **管理接口限速**15分钟内最多100次请求
---
## 日志
- 运行日志:`data/logs/combined.log`(自动轮转,单文件10MB
- 错误日志:`data/logs/error.log`
- 操作记录:SQLite 数据库 `data/automation.db`(可通过管理后台查看)
---
## 故障排查
| 问题 | 可能原因 | 解决方法 |
|------|---------|---------|
| 飞书事件收不到 | 回调地址不通/应用未发布 | 检查公网访问、确认应用已审核通过 |
| 群晖操作失败 | Session 过期/权限不足 | 检查账号权限、确认 FileStation API 开启 |
| JumpServer 命令超时 | 资产连接慢/网络问题 | 增加 timeout、检查 ic1 连通性 |
| Nextcloud 403 | 权限不足/共享功能未启用 | 检查用户权限、启用 files_sharing |
| 审批意见提交失败 | 无待处理任务 | 确认审批流程中有机器人审批节点 |