ci: 归档 ECS 专用工作流;新增 NAS 自动部署流水线

This commit is contained in:
2026-10-10 16:33:29 +08:00
parent 0593ff7e62
commit a41a6644a4
17 changed files with 45 additions and 0 deletions
+106
View File
@@ -0,0 +1,106 @@
name: Grant Super Admin (设超管 · 可带外建号)
# 超管不是"某个预置账号+密码"——代码里没有种子管理员、密码全是 salt+hash 不可反推。
# 超管 = .env 的 SUPER_ADMIN_EMAILS 白名单:【白名单里的邮箱,谁拥有这个账号,谁就是超管】。
#
# ⚠ 重要(安全策略变更后的正确顺序):
# 为堵住"管理员邮箱可被任何人抢注→拿全部后台权限"的漏洞,后端【已禁止用白名单邮箱自助注册】。
# 所以【先加白名单、再去注册】这条老路已经走不通(注册会被 403 挡掉)。
# 现在有两条路:
# A) 已有账号:你的邮箱【已经】在平台注册过 → 直接跑本工作流加白名单 → 重新登录即为超管。
# B) 没有账号:勾选 create_or_reset_account → 本工作流【带外】在库里建号/重置密码(密码取自
# 仓库 Secret: ADMIN_INIT_PASSWORD)→ 加白名单 → 用该邮箱+该密码登录即为超管。
#
# 走 B 之前请先在 GitHub 仓库 Settings → Secrets and variables → Actions 添加:
# ADMIN_INIT_PASSWORD = 你的强密码(≥8位)。用 Secret 而不是工作流输入框——输入框的值会明文
# 留在 Actions 运行记录里,Secret 会在日志中被自动打码。
#
# 前置:后端需已部署过(含 scripts/create-admin.js)。若提示脚本不存在,先跑一次后端部署工作流。
on:
workflow_dispatch:
inputs:
admin_email:
description: '要设为超管的邮箱(用你自己的)'
required: true
type: string
create_or_reset_account:
description: '带外建号/重置密码(账号还不存在、或忘了密码时勾选;密码取自 Secret ADMIN_INIT_PASSWORD)'
required: false
default: false
type: boolean
delete_orphan_admin:
description: '同时删除误建的孤儿账号 admin@test.com(密码随机无人知道,建议删)'
required: false
default: true
type: boolean
jobs:
grant:
runs-on: ubuntu-latest
steps:
- name: Set SUPER_ADMIN_EMAILS (+ optional out-of-band account provisioning)
uses: appleboy/ssh-action@v1
env:
ADMIN_EMAIL: ${{ inputs.admin_email }}
ADMIN_PASSWORD: ${{ secrets.ADMIN_INIT_PASSWORD }}
DO_CREATE: ${{ inputs.create_or_reset_account }}
DO_DELETE_ORPHAN: ${{ inputs.delete_orphan_admin }}
with:
host: ${{ secrets.ECS_HOST }}
username: ${{ secrets.ECS_USER }}
password: ${{ secrets.ECS_PASSWORD }}
command_timeout: 5m
envs: ADMIN_EMAIL,ADMIN_PASSWORD,DO_CREATE,DO_DELETE_ORPHAN
script: |
set -e
cd /var/www/digitalme-api.invoratec.cn
[ -f .env ] || { echo "❌ 生产 .env 缺失,中止"; exit 1; }
echo "──── 当前 SUPER_ADMIN_EMAILS ────"
grep '^SUPER_ADMIN_EMAILS=' .env || echo "(未设置 → 现在没有任何人是超管)"
EMAIL="$(echo "$ADMIN_EMAIL" | tr '[:upper:]' '[:lower:]' | tr -d ' ')"
if [ -z "$EMAIL" ]; then echo "❌ 邮箱为空"; exit 1; fi
# ── 带外建号/重置密码(账号不存在时的唯一入口,因为白名单邮箱已禁止自助注册) ──
if [ "$DO_CREATE" = "true" ]; then
if [ -z "$ADMIN_PASSWORD" ]; then
echo "❌ 勾了「带外建号」但仓库 Secret ADMIN_INIT_PASSWORD 未设置。"
echo " 去 GitHub → Settings → Secrets and variables → Actions 添加 ADMIN_INIT_PASSWORD(≥8位) 再重跑。"
exit 1
fi
[ -f scripts/create-admin.js ] || { echo "❌ 服务器上没有 scripts/create-admin.js —— 请先跑一次【后端部署】工作流再来。"; exit 1; }
echo "──── 带外建号/重置密码 ────"
ADMIN_EMAIL="$EMAIL" ADMIN_PASSWORD="$ADMIN_PASSWORD" node scripts/create-admin.js
fi
# ── 写入/覆盖超管白名单(只放这一个邮箱,最小权限) ──
if grep -q '^SUPER_ADMIN_EMAILS=' .env; then
sed -i "s|^SUPER_ADMIN_EMAILS=.*|SUPER_ADMIN_EMAILS=$EMAIL|" .env
else
echo "SUPER_ADMIN_EMAILS=$EMAIL" >> .env
fi
echo "──── 写入后 ────"
grep '^SUPER_ADMIN_EMAILS=' .env
# 删掉被误建的孤儿账号 admin@test.com(随机密码、无人知道、白占邮箱)
if [ "$DO_DELETE_ORPHAN" = "true" ] && [ "$EMAIL" != "admin@test.com" ]; then
MONGO_URI="$(grep '^MONGO_URI=' .env | cut -d= -f2- || echo 'mongodb://localhost:27017')"
MONGO_DB="$(grep '^MONGO_DB=' .env | cut -d= -f2- || echo 'creator_cn')"
echo "──── 删除孤儿账号 admin@test.com ────"
mongosh "$MONGO_URI/$MONGO_DB" --quiet --eval '
const u = db.users.findOne({ email: "admin@test.com" });
if (!u) { print("admin@test.com 不存在,无需清理"); }
else {
const r = db.users.deleteOne({ _id: u._id });
print("已删除 admin@test.com,deletedCount=" + r.deletedCount);
}
' || echo "⚠ mongosh 执行失败(可手动清理),不影响超管设置"
fi
# 重启后端让新的 .env 生效
pm2 restart digitalme-api --update-env
pm2 describe digitalme-api | grep -E 'status|restarts' || true
echo "✅ 完成。用 $EMAIL 登录 → 即为超管(右上角出现盾牌图标 / 可进 /admin)。"
echo " 若刚带外建号:用你在 Secret ADMIN_INIT_PASSWORD 里设的密码登录,登录后建议立刻改密。"