{section.title}
+{section.body}
+diff --git a/server-patches/patch-email-verification.js b/server-patches/patch-email-verification.js deleted file mode 100644 index bfc1967..0000000 --- a/server-patches/patch-email-verification.js +++ /dev/null @@ -1,291 +0,0 @@ -const fs = require("fs"); - -// ── Patch 1: context.js ────────────────────────────────────── -const ctxPath = "/opt/omniai-server/src/routes/context.js"; -let ctx = fs.readFileSync(ctxPath, "utf8"); - -const smsMaxLine = "const SMS_CODE_MAX_ATTEMPTS = Math.max(1, Number(process.env.SMS_CODE_MAX_ATTEMPTS) || 5);"; -const emailConsts = ` -const EMAIL_PURPOSES = new Set(["register", "login", "reset"]); -const EMAIL_CODE_TTL_MINUTES = Math.max(1, Number(process.env.EMAIL_CODE_TTL_MINUTES) || 10); -const EMAIL_CODE_COOLDOWN_SECONDS = Math.max(10, Number(process.env.EMAIL_CODE_COOLDOWN_SECONDS) || 60); -const EMAIL_CODE_MAX_ATTEMPTS = Math.max(1, Number(process.env.EMAIL_CODE_MAX_ATTEMPTS) || 5);`; - -if (!ctx.includes("EMAIL_PURPOSES")) { - ctx = ctx.replace(smsMaxLine, smsMaxLine + emailConsts); - console.log("[ctx] added EMAIL_PURPOSES"); -} - -const afterConsume = ' await pool.query("UPDATE sms_verification_codes SET consumed_at = NOW() WHERE id = $1", [row.id]);\n return true;\n}'; -const emailFuncs = ` -function hashEmailCode(email, code) { - const secret = process.env.EMAIL_CODE_SECRET || process.env.JWT_SECRET || "omniai-dev-email-secret"; - return crypto.createHash("sha256").update(email + ":" + code + ":" + secret).digest("hex"); -} - -async function sendEmailCode(email, code, purpose) { - const provider = String(process.env.EMAIL_PROVIDER || "mock").trim().toLowerCase(); - - if (provider === "smtp") { - const nodemailer = require("nodemailer"); - const transporter = nodemailer.createTransport({ - host: process.env.SMTP_HOST, - port: Number(process.env.SMTP_PORT) || 587, - secure: process.env.SMTP_SECURE === "1", - auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS }, - }); - - const purposeText = purpose === "register" ? "\u6ce8\u518c" : purpose === "login" ? "\u767b\u5f55" : "\u91cd\u7f6e\u5bc6\u7801"; - await transporter.sendMail({ - from: process.env.SMTP_FROM || process.env.SMTP_USER, - to: email, - subject: "[OmniAI] \u90ae\u7bb1\u9a8c\u8bc1\u7801", - text: "\u60a8\u7684\u9a8c\u8bc1\u7801\u662f\uff1a" + code + "\n\u7528\u9014\uff1a" + purposeText + "\n\u6709\u6548\u671f\uff1a" + String(process.env.EMAIL_CODE_TTL_MINUTES || 10) + " \u5206\u949f\n\u5982\u679c\u4e0d\u662f\u60a8\u672c\u4eba\u64cd\u4f5c\uff0c\u8bf7\u5ffd\u7565\u6b64\u90ae\u4ef6\u3002", - html: '
\u60a8\u7684\u9a8c\u8bc1\u7801\u662f\uff1a
' + code + '
\u7528\u9014\uff1a' + purposeText + '
\u6709\u6548\u671f\uff1a' + String(process.env.EMAIL_CODE_TTL_MINUTES || 10) + ' \u5206\u949f
\u5982\u679c\u4e0d\u662f\u60a8\u672c\u4eba\u64cd\u4f5c\uff0c\u8bf7\u5ffd\u7565\u6b64\u90ae\u4ef6\u3002
我们使用 Cookie 和本地存储保存登录状态、偏好设置、创作草稿和断点续传数据,用于保障服务正常运行。
+{companyName} 平台服务合规说明。更新日期:2026 年 6 月 3 日。
+{section.body}
+