canglan a11df22600 feat: system logs - email log + system log with admin UI
- db: email_logs (sent/failed) + system_logs (info/warn/error) tables,
  auto-migrated for existing installs
- backend/logger.js: logEmail/logSystem with try/catch (never breaks flow)
- mailer: log send result (SMTP unconfigured/sent/failed + error msg)
- webhook: log blocked-internal, non-2xx response, send failure
- server: error middleware records 500 errors to system_logs
- routes/logs.js: GET /logs/emails + /logs/system (admin/owner, filters)
- UI: 系统日志 page (owner/admin) with system/email tabs + filters
- API docs updated
2026-08-17 05:14:41 +08:00

MC Report System

游戏玩家投诉/建议/申诉系统。Web 端 + Paper 插件双端提交MySQL 存储JWT 鉴权,三级角色。

功能模块

模块 说明
举报 指定目标玩家或事项举报,可上传截图/视频≤50MB支持投诉管理员仅服主可见
建议 提交改进建议,仅服主处理
申诉 封禁申诉 + 结果申诉(对处理结果不满可提交一次,关联原工单)
审批流 待处理→接单→处理中→待补充→已解决/已驳回→关闭7天自动关闭
接单制 管理员一人一单,可转单(带原因),处理备注(玩家不可见)
投票 分组/子服管理,定时/不定时投票,盲投制,管理员 1.5 票权
更新内容 Issues 风格,分状态(待定/计划中/已完成),讨论区,按时间/热度排序,分组筛选
通知 SMTP 邮件 + Discord WebhookSSRF 防护),邮件模板自定义(编辑变量)
导出 CSVUTF-8 BOM导出工单/被举报人统计/操作日志(仅服主)
插件 Paper 1.20+,统一 /report 命令,游戏内注册/登录/举报/追踪
找回密码 邮箱验证1小时有效重置链接
多来源身份 一个账号可同时绑定网易端 + 皮肤站身份,提交工单时选择身份
安装向导 Web 页面配置 MySQL 连接 + 创建服主账号(完成后无需重启)

API 文档

完整接口文档见 docs/API.md(认证/工单/封禁/用户/设置/通知/投票/更新/导出/外部插件 API

快速开始

npm install
node backend/server.js
# → 打开 http://localhost:3100/#/install

两步安装:填 MySQL 连接信息 → 建服主账号 → 重启生效。

默认端口

3100,可通过 PORT=8080 环境变量修改。

技术栈

技术
后端 Node.js + Express + mysql2
前端 Vanilla JS SPAHash路由+ Inter 字体
数据库 MySQL ≥ 5.7
认证 JWT256 位随机密钥72h 有效期)
安全 Helmet 7 + Rate Limit分路由限速+ XSS 过滤 + CSP + API Key 常量时间比对 + SSRF 防护
验证码 SVG 混淆图片svg-captcha4 位字符 + 噪点 + 颜色变形)
文件上传 Multer + MIME + 魔数字节校验UUID 命名web 外存储
插件 Paper API 1.20.4 + java.net.HttpURLConnection

角色权限矩阵

操作 玩家 管理员 服主
提交工单
查看工单 仅自己 待处理 + 自己接的 全部
查看详情 仅自己 待处理 + 自己接的 全部
接单认领 举报/申诉 全部
更新处理备注 自己接的 全部
变更状态 自己接的 全部
转单 自己接的 全部
回复工单 自己的
用户管理
邮件模板
通知配置
系统设置
导出数据
投票/更新管理
工单追加(未接单) 自己的

审批流状态

待处理(pending) ──接单──→ 处理中(processing) ──→ 已解决(resolved)
    │                          │                    ├── 已驳回(rejected)
    │                    待补充(awaiting_info)       └── 7天自动关闭(closed)
    │                          │
    └── 结果申诉 ──→ 申诉中(appealing) ──服主处理──→ 原工单关闭
  • closed 为终态,仅服主可操作
  • 结果申诉仅一次,关联原工单,仅服主可见

注册来源与多身份

来源 标识 UID 含义
网易端 netease 网易 UID
皮肤站 skin 皮肤站 UID / Minecraft UUID

插件注册默认 skin

多身份绑定:一个账号可同时绑定网易端 + 皮肤站两个身份(控制台「我的身份」或 POST /api/auth/identities 管理)。提交工单时可选择使用哪个身份;user_identities 表由启动时自动迁移回填,users 表主身份字段保持不变(完全兼容旧数据)。

工单提交流程

  1. 填写标题 + 游戏名 + UID登录后自动填充
  2. 举报:选目标玩家 + 原因(内置选项或自定义)+ 可投诉管理员
  3. 建议:填写建议内容
  4. 申诉:填写封禁申诉理由
  5. 上传附件(可选,图片/视频 ≤50MB最多5个
  6. 提交 → 生成 tracking_tokenCookie 留存)

外部 API

端点 用途 认证
POST /api/external/auth/register 插件注册 x-external-key
POST /api/external/auth/login 插件登录 x-external-key
GET /api/external/my-tickets 我的工单(JWT) x-external-key + Bearer
GET /api/external/my-tickets/:id 工单详情(JWT) x-external-key + Bearer
POST /api/external/tickets 提交工单 x-external-key
GET /api/external/all-tickets 全部工单 x-external-key
GET /api/external/reported-players 被举报统计 x-external-key
GET /api/external/stats 统计 x-external-key

部署

# 环境变量
PORT=3100 CORS_ORIGIN=https://your-domain.com node backend/server.js

# PM2 持久化
pm2 start backend/server.js --name mc-report

# Nginx 反代(还需 include nginx.inc
proxy_pass http://127.0.0.1:3100;

插件命令

/report reg <密码> <邮箱> [用户名]    注册(默认用户=游戏名)
/report login <密码> [用户名]        登录
/report report [玩家] <原因>         举报
/report suggest <内容>              建议
/report track [id]                  追踪工单

配置 plugins/MCReport/config.yml 填写 api_urlexternal_key

目录结构

├── backend/
│   ├── server.js              # Express 入口
│   ├── db.js                  # MySQL 连接池 + 建表 + 迁移
│   ├── mailer.js              # SMTP 邮件(缓存 transporter
│   ├── webhook.js             # Discord WebhookSSRF 防护 + 10s 超时)
│   ├── middleware/
│   │   ├── auth.js            # JWT惰性缓存 secret
│   │   ├── security.js        # 限速 + XSS 递归 + API Key 常量时间比对
│   │   └── upload.js          # 文件上传(仅读 256B 头验证魔数)
│   └── routes/
│       ├── auth.js            # 注册/登录/验证/找回密码
│       ├── tickets.js         # 工单核心(自动关闭 + 状态流转)
│       ├── install.js         # 安装向导(含 api_key 生成)
│       ├── external.js        # 外部 API插件 + Java 服务器)
│       ├── users.js           # 用户管理(含 source 字段)
│       ├── settings.js        # 站点设置 + 邮件模板编辑
│       ├── export.js          # CSV 导出(服主专享)
│       ├── polls.js           # 投票(分组/子服/定时)
│       ├── features.js        # 更新内容Issues 风格 + 讨论)
│       ├── notifications.js   # Webhook 配置
│       ├── captcha.js         # SVG 验证码
│       └── uploads.js         # 附件下载(鉴权)
├── public/                    # 前端 SPA (16 页面)
├── mc-report-plugin/          # Paper 1.20+ 插件 (Maven)
├── nginx.inc                  # Nginx 额外配置
├── data/                      # config.json + uploads/
├── README.md
└── package.json

安全

措施 实现
JWT 秘钥 256 位随机,惰性缓存,无硬编码 fallback
API Key 48 位随机,常量时间比对防时序攻击
限速 登录 8/min、注册 3/min、工单 10/min、全局 300/min
XSS sanitizeBody 递归过滤 + U.esc 前端转义
CSP Helmet + script-src-attr 'unsafe-inline'
SQL 注入 全参数化查询
文件上传 扩展名 + MIME + 魔数(仅读 256B+ UUID 命名
Webhook SSRF DNS 解析后过滤内网 IP
用户名枚举 注册/登录统一错误信息
CORS 环境变量控制 + localhost 自动放行
Description
No description provided
Readme 2.4 MiB
Languages
JavaScript 94.9%
CSS 4.6%
HTML 0.5%