update
This commit is contained in:
@@ -1,21 +1,30 @@
|
||||
import { Request, Response } from 'express';
|
||||
import { NotificationService } from '../services/notification.service';
|
||||
import { NotificationSetting } from '../types/notification.types';
|
||||
import { AuditLogService } from '../services/audit.service';
|
||||
import { NotificationSettingsRepository } from '../repositories/notification.repository'; // Use repository
|
||||
import { NotificationSetting, NotificationChannelType, NotificationChannelConfig, WebhookConfig, EmailConfig, TelegramConfig, NotificationEvent } from '../types/notification.types';
|
||||
import { AuditLogService } from '../services/audit.service'; // Keep for now if other parts use it
|
||||
import { AppEventType, default as eventService } from '../services/event.service'; // Import event service
|
||||
|
||||
const auditLogService = new AuditLogService();
|
||||
// Remove sender imports as they are no longer called directly for testing
|
||||
// import telegramSenderService from '../services/senders/telegram.sender.service';
|
||||
// import emailSenderService from '../services/senders/email.sender.service';
|
||||
// import webhookSenderService from '../services/senders/webhook.sender.service';
|
||||
// import { ProcessedNotification } from '../services/notification.processor.service'; // Not needed here
|
||||
|
||||
// Removed escapeTelegramMarkdownV2 helper function
|
||||
|
||||
const auditLogService = new AuditLogService(); // Keep for now if other parts use it, but prefer eventService
|
||||
|
||||
export class NotificationController {
|
||||
private notificationService: NotificationService;
|
||||
private repository: NotificationSettingsRepository; // Use repository
|
||||
|
||||
constructor() {
|
||||
this.notificationService = new NotificationService();
|
||||
this.repository = new NotificationSettingsRepository(); // Instantiate repository
|
||||
}
|
||||
|
||||
// GET /api/v1/notifications
|
||||
getAll = async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const settings = await this.notificationService.getAllSettings();
|
||||
const settings = await this.repository.getAll(); // Use repository
|
||||
res.status(200).json(settings);
|
||||
} catch (error: any) {
|
||||
res.status(500).json({ message: '获取通知设置失败', error: error.message });
|
||||
@@ -32,11 +41,14 @@ export class NotificationController {
|
||||
}
|
||||
|
||||
try {
|
||||
const newSettingId = await this.notificationService.createSetting(settingData);
|
||||
const newSetting = await this.notificationService.getSettingById(newSettingId);
|
||||
// 记录审计日志
|
||||
const newSettingId = await this.repository.create(settingData); // Use repository
|
||||
const newSetting = await this.repository.getById(newSettingId);
|
||||
// 记录审计日志 (Use event service)
|
||||
if (newSetting) {
|
||||
auditLogService.logAction('NOTIFICATION_SETTING_CREATED', { settingId: newSetting.id, name: newSetting.name, type: newSetting.channel_type });
|
||||
eventService.emitEvent(AppEventType.NotificationSettingCreated, {
|
||||
userId: (req.session as any).userId, // Assuming userId is in session
|
||||
details: { settingId: newSetting.id, name: newSetting.name, type: newSetting.channel_type }
|
||||
});
|
||||
}
|
||||
res.status(201).json(newSetting);
|
||||
} catch (error: any) {
|
||||
@@ -59,11 +71,14 @@ export class NotificationController {
|
||||
}
|
||||
|
||||
try {
|
||||
const success = await this.notificationService.updateSetting(id, settingData);
|
||||
const success = await this.repository.update(id, settingData); // Use repository
|
||||
if (success) {
|
||||
const updatedSetting = await this.notificationService.getSettingById(id);
|
||||
// 记录审计日志
|
||||
auditLogService.logAction('NOTIFICATION_SETTING_UPDATED', { settingId: id, updatedFields: Object.keys(settingData) });
|
||||
const updatedSetting = await this.repository.getById(id);
|
||||
// 记录审计日志 (Use event service)
|
||||
eventService.emitEvent(AppEventType.NotificationSettingUpdated, {
|
||||
userId: (req.session as any).userId,
|
||||
details: { settingId: id, updatedFields: Object.keys(settingData) }
|
||||
});
|
||||
res.status(200).json(updatedSetting);
|
||||
} else {
|
||||
res.status(404).json({ message: `未找到 ID 为 ${id} 的通知设置` });
|
||||
@@ -83,81 +98,100 @@ export class NotificationController {
|
||||
}
|
||||
|
||||
try {
|
||||
const success = await this.notificationService.deleteSetting(id);
|
||||
const settingToDelete = await this.repository.getById(id); // Get details before deleting for audit log
|
||||
if (!settingToDelete) {
|
||||
res.status(404).json({ message: `未找到 ID 为 ${id} 的通知设置` });
|
||||
return;
|
||||
}
|
||||
const success = await this.repository.delete(id); // Use repository
|
||||
if (success) {
|
||||
// 记录审计日志
|
||||
auditLogService.logAction('NOTIFICATION_SETTING_DELETED', { settingId: id });
|
||||
// 记录审计日志 (Use event service)
|
||||
eventService.emitEvent(AppEventType.NotificationSettingDeleted, {
|
||||
userId: (req.session as any).userId,
|
||||
details: { settingId: id, name: settingToDelete.name, type: settingToDelete.channel_type } // Include name/type in audit
|
||||
});
|
||||
res.status(204).send(); // No Content
|
||||
} else {
|
||||
res.status(404).json({ message: `未找到 ID 为 ${id} 的通知设置` });
|
||||
// Should not happen if getById succeeded, but handle defensively
|
||||
res.status(404).json({ message: `删除 ID 为 ${id} 的通知设置失败,可能已被删除` });
|
||||
}
|
||||
} catch (error: any) {
|
||||
res.status(500).json({ message: '删除通知设置失败', error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// --- Refactored Test Endpoints ---
|
||||
|
||||
// Removed executeTestSend method as testing now goes through the event system
|
||||
|
||||
// POST /api/v1/notifications/:id/test
|
||||
// Tests an existing, saved setting configuration by triggering a test event
|
||||
testSetting = async (req: Request, res: Response): Promise<void> => {
|
||||
const id = parseInt(req.params.id, 10);
|
||||
const { config } = req.body;
|
||||
|
||||
if (isNaN(id)) {
|
||||
res.status(400).json({ message: '无效的通知设置 ID' });
|
||||
return;
|
||||
}
|
||||
if (!config) {
|
||||
res.status(400).json({ message: '缺少用于测试的配置信息' });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const originalSetting = await this.notificationService.getSettingById(id);
|
||||
if (!originalSetting) {
|
||||
const settingToTest = await this.repository.getById(id);
|
||||
if (!settingToTest) {
|
||||
res.status(404).json({ message: `未找到 ID 为 ${id} 的通知设置` });
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await this.notificationService.testSetting(originalSetting.channel_type, config);
|
||||
// Trigger the standard test event, passing the config to be used by the processor
|
||||
eventService.emitEvent(AppEventType.TestNotification, {
|
||||
userId: (req.session as any).userId, // Optional: associate test with user
|
||||
details: {
|
||||
message: `为设置 ID ${id} (${settingToTest.name}) 触发的测试`,
|
||||
testTargetConfig: settingToTest.config, // Pass the config to use
|
||||
testTargetChannelType: settingToTest.channel_type // Pass the channel type
|
||||
}
|
||||
});
|
||||
|
||||
// Respond immediately confirming the event was triggered
|
||||
res.status(200).json({ message: '测试通知事件已触发。请检查对应渠道的接收情况。' });
|
||||
|
||||
if (result.success) {
|
||||
// 记录审计日志 (可选,根据需要决定是否记录测试操作)
|
||||
|
||||
res.status(200).json({ message: result.message });
|
||||
} else {
|
||||
// 记录审计日志 (可选)
|
||||
|
||||
res.status(500).json({ message: result.message });
|
||||
}
|
||||
} catch (error: any) {
|
||||
res.status(500).json({ message: '测试通知设置时发生内部错误', error: error.message });
|
||||
console.error(`[NotificationController] Error triggering test for setting ${id}:`, error);
|
||||
res.status(500).json({ message: '触发测试通知时发生内部错误', error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// POST /api/v1/notifications/test-unsaved
|
||||
// Tests configuration data provided in the request body by triggering a test event
|
||||
testUnsavedSetting = async (req: Request, res: Response): Promise<void> => {
|
||||
const { channel_type, config } = req.body;
|
||||
const { channel_type, config } = req.body as { channel_type: NotificationChannelType, config: NotificationChannelConfig };
|
||||
|
||||
if (!channel_type || !config) {
|
||||
res.status(400).json({ message: '缺少必要的测试信息 (channel_type, config)' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Basic validation for channel type
|
||||
if (!['webhook', 'email', 'telegram'].includes(channel_type)) {
|
||||
res.status(400).json({ message: '无效的渠道类型' });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this.notificationService.testSetting(channel_type, config);
|
||||
// Trigger the standard test event, passing the unsaved config to be used by the processor
|
||||
eventService.emitEvent(AppEventType.TestNotification, {
|
||||
userId: (req.session as any).userId,
|
||||
details: {
|
||||
message: `为未保存的 ${channel_type} 配置触发的测试`,
|
||||
testTargetConfig: config, // Pass the unsaved config to use
|
||||
testTargetChannelType: channel_type // Pass the channel type
|
||||
}
|
||||
});
|
||||
|
||||
// Respond immediately confirming the event was triggered
|
||||
res.status(200).json({ message: '测试通知事件已触发。请检查对应渠道的接收情况。' });
|
||||
|
||||
if (result.success) {
|
||||
res.status(200).json({ message: result.message });
|
||||
} else {
|
||||
res.status(500).json({ message: result.message });
|
||||
}
|
||||
} catch (error: any) {
|
||||
res.status(500).json({ message: '测试通知设置时发生内部错误', error: error.message });
|
||||
console.error(`[NotificationController] Error triggering test for unsaved ${channel_type}:`, error);
|
||||
res.status(500).json({ message: '触发测试通知时发生内部错误', error: error.message });
|
||||
}
|
||||
};
|
||||
}
|
||||
} // End of class NotificationController
|
||||
|
||||
Reference in New Issue
Block a user