# 文件传输自动化系统 飞书审批驱动的企业文件传输与权限自动化管理系统。 ## 系统架构 ``` 飞书审批事件 ──→ Express 服务 ──→ 群晖 NAS API(文件复制) │ ──→ JumpServer API(远程命令) │ ──→ Nextcloud API(文件共享) │ ├── SQLite(操作日志) ├── 管理后台(Web UI) └── 飞书机器人(告警通知) ``` ## 快速开始 ### 1. 环境要求 - Node.js >= 18 - 可访问群晖 NAS、JumpServer、Nextcloud 的网络 - 公网 IP 或域名(用于飞书事件回调) ### 2. 安装部署 ```bash # 克隆项目 git clone 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 | | 审批意见提交失败 | 无待处理任务 | 确认审批流程中有机器人审批节点 |