Files
wingautomation/README.md
T
2026-07-24 11:34:38 +08:00

317 lines
9.3 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.
# 文件传输自动化系统
飞书审批驱动的企业文件传输与权限自动化管理系统。
## 系统架构
```
飞书审批事件 ──→ 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 |
| 审批意见提交失败 | 无待处理任务 | 确认审批流程中有机器人审批节点 |