fix: data-action buttons, sources enabled, email notify, ticket detail single-page
- app.js: mount page objects via inline script (CSP blocks eval → data-action buttons dead) - app.js: add tickets list entry to sidebar nav (admin could not find claimed tickets) - sources: GET /sources?manage=1 returns enabled field for admin view - mailer: sendNotifyEmail consumes email-type notification_configs (webhook_url = recipients) - tickets: trigger notify on created/claimed/transferred/updated/status-change - notifications: email type shows recipient field, validates email list - ticket-detail: single-page chat flow (player/staff bubbles) + processing log timeline - css: chat bubble styles
This commit is contained in:
@@ -33,11 +33,19 @@ async function validateNotify(body) {
|
||||
if (name !== undefined && (!name || String(name).length > 100)) return '名称不能为空且不超过100字符';
|
||||
if (type !== undefined && !NOTIFY_TYPES.includes(type)) return '无效的通知类型';
|
||||
if (webhook_url !== undefined && webhook_url !== '') {
|
||||
let u;
|
||||
try { u = new URL(webhook_url); } catch { return 'Webhook地址格式无效'; }
|
||||
if (u.protocol !== 'https:' && u.protocol !== 'http:') return 'Webhook地址协议不支持';
|
||||
if (await isPrivateUrl(webhook_url)) return 'Webhook地址不允许指向内网';
|
||||
if (type === 'email') {
|
||||
// email 类型: webhook_url 复用为收件人邮箱(逗号分隔)
|
||||
const emails = String(webhook_url).split(',').map(s => s.trim()).filter(Boolean);
|
||||
if (!emails.length) return '收件人邮箱不能为空';
|
||||
if (!emails.every(e => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e))) return '收件人邮箱格式无效';
|
||||
} else {
|
||||
let u;
|
||||
try { u = new URL(webhook_url); } catch { return 'Webhook地址格式无效'; }
|
||||
if (u.protocol !== 'https:' && u.protocol !== 'http:') return 'Webhook地址协议不支持';
|
||||
if (await isPrivateUrl(webhook_url)) return 'Webhook地址不允许指向内网';
|
||||
}
|
||||
}
|
||||
if (type === 'email' && !webhook_url) return '邮件通知需填写收件人邮箱';
|
||||
if (events !== undefined) {
|
||||
const list = String(events).split(',').map(s => s.trim());
|
||||
if (!list.every(e => NOTIFY_EVENTS.includes(e))) return '无效的触发事件';
|
||||
|
||||
Reference in New Issue
Block a user