321 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			321 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | const express = require('express'); | |||
|  | const { auth } = require('../middleware/auth'); | |||
|  | const { validateQuery, validate } = require('../middleware/validation'); | |||
|  | const { logger } = require('../config/logger'); | |||
|  | const { HTTP_STATUS } = require('../config/constants'); | |||
|  | const { getDB } = require('../database'); | |||
|  | const Joi = require('joi'); | |||
|  | 
 | |||
|  | const router = express.Router(); | |||
|  | 
 | |||
|  | /** | |||
|  |  * 系统设置验证规则 | |||
|  |  */ | |||
|  | const systemSchemas = { | |||
|  |   // 更新系统设置
 | |||
|  |   updateSettings: Joi.object({ | |||
|  |     basic: Joi.object({ | |||
|  |       siteName: Joi.string().max(100).allow(''), | |||
|  |       siteDescription: Joi.string().max(500).allow(''), | |||
|  |       siteKeywords: Joi.string().max(200).allow(''), | |||
|  |       siteLogo: Joi.string().allow(''), | |||
|  |       siteFavicon: Joi.string().allow(''), | |||
|  | 
 | |||
|  |       icp: Joi.string().max(100).allow('') | |||
|  |     }).optional(), | |||
|  |     features: Joi.object({ | |||
|  |       allowRegister: Joi.boolean(), | |||
|  |       allowTransfer: Joi.boolean(), | |||
|  |       allowExchange: Joi.boolean(), | |||
|  |       allowReview: Joi.boolean(), | |||
|  |       allowComment: Joi.boolean() | |||
|  |     }).optional(), | |||
|  | 
 | |||
|  |     security: Joi.object({ | |||
|  |       maxLoginAttempts: Joi.number().integer().min(1).max(100), | |||
|  |       lockoutDuration: Joi.number().integer().min(1).max(86400), | |||
|  |       ipWhitelist: Joi.string().allow('') | |||
|  |     }).optional() | |||
|  |   }) | |||
|  | }; | |||
|  | 
 | |||
|  | /** | |||
|  |  * 获取系统设置 (公开接口,不需要认证) | |||
|  |  * GET /api/system/settings | |||
|  |  */ | |||
|  | router.get('/settings', async (req, res, next) => { | |||
|  |   try { | |||
|  | 
 | |||
|  |     const db = getDB(); | |||
|  |      | |||
|  |     // 获取系统设置
 | |||
|  |     const [settings] = await db.execute( | |||
|  |       'SELECT setting_key, setting_value FROM system_settings' | |||
|  |     ); | |||
|  | 
 | |||
|  |     // 组织设置数据
 | |||
|  |     const settingsData = { | |||
|  |       basic: { | |||
|  |         siteName: '', | |||
|  |         siteDescription: '', | |||
|  |         siteKeywords: '', | |||
|  |         siteLogo: '', | |||
|  |         siteFavicon: '', | |||
|  | 
 | |||
|  |         icp: '' | |||
|  |       }, | |||
|  |       features: { | |||
|  |         allowRegister: true, | |||
|  |         allowTransfer: true, | |||
|  |         allowExchange: true, | |||
|  |         allowReview: true, | |||
|  |         allowComment: true | |||
|  |       }, | |||
|  | 
 | |||
|  |       security: { | |||
|  |         maxLoginAttempts: 5, | |||
|  |         lockoutDuration: 300, | |||
|  |         ipWhitelist: '' | |||
|  |       } | |||
|  |     }; | |||
|  | 
 | |||
|  |     // 填充数据库中的设置
 | |||
|  |     settings.forEach(setting => { | |||
|  |       const keys = setting.setting_key.split('.'); | |||
|  |       if (keys.length === 2 && settingsData[keys[0]]) { | |||
|  |         try { | |||
|  |           // 尝试解析JSON值,如果失败则使用原始值
 | |||
|  |           settingsData[keys[0]][keys[1]] = JSON.parse(setting.setting_value); | |||
|  |         } catch { | |||
|  |           settingsData[keys[0]][keys[1]] = setting.setting_value; | |||
|  |         } | |||
|  |       } | |||
|  |     }); | |||
|  | 
 | |||
|  |     logger.info('System settings retrieved', { | |||
|  |       settingsCount: settings.length | |||
|  |     }); | |||
|  | 
 | |||
|  |     res.json({ | |||
|  |       success: true, | |||
|  |       data: settingsData | |||
|  |     }); | |||
|  |   } catch (error) { | |||
|  |     next(error); | |||
|  |   } | |||
|  | }); | |||
|  | 
 | |||
|  | /** | |||
|  |  * 更新系统设置 | |||
|  |  * PUT /api/system/settings | |||
|  |  */ | |||
|  | router.put('/settings',  | |||
|  |   auth,  | |||
|  |   validate(systemSchemas.updateSettings),  | |||
|  |   async (req, res, next) => { | |||
|  |     try { | |||
|  |       // 检查管理员权限
 | |||
|  |       if (req.user.role !== 'admin') { | |||
|  |         return res.status(HTTP_STATUS.FORBIDDEN).json({ | |||
|  |           success: false, | |||
|  |           message: '权限不足' | |||
|  |         }); | |||
|  |       } | |||
|  | 
 | |||
|  |       const db = getDB(); | |||
|  |       const settings = req.body; | |||
|  | 
 | |||
|  |       // 开始事务
 | |||
|  |       await db.beginTransaction(); | |||
|  | 
 | |||
|  |       try { | |||
|  |         // 更新设置
 | |||
|  |         for (const [category, categorySettings] of Object.entries(settings)) { | |||
|  |           for (const [key, value] of Object.entries(categorySettings)) { | |||
|  |             const settingKey = `${category}.${key}`; | |||
|  |             const settingValue = JSON.stringify(value); | |||
|  | 
 | |||
|  |             await db.execute( | |||
|  |               `INSERT INTO system_settings (setting_key, setting_value, updated_at) 
 | |||
|  |                VALUES (?, ?, NOW())  | |||
|  |                ON DUPLICATE KEY UPDATE  | |||
|  |                setting_value = VALUES(setting_value),  | |||
|  |                updated_at = VALUES(updated_at)`,
 | |||
|  |               [settingKey, settingValue] | |||
|  |             ); | |||
|  |           } | |||
|  |         } | |||
|  | 
 | |||
|  |         await db.commit(); | |||
|  | 
 | |||
|  |         logger.info('System settings updated', { | |||
|  |           userId: req.user.id, | |||
|  |           categories: Object.keys(settings) | |||
|  |         }); | |||
|  | 
 | |||
|  |         res.json({ | |||
|  |           success: true, | |||
|  |           message: '系统设置更新成功' | |||
|  |         }); | |||
|  |       } catch (error) { | |||
|  |         await db.rollback(); | |||
|  |         throw error; | |||
|  |       } | |||
|  |     } catch (error) { | |||
|  |       next(error); | |||
|  |     } | |||
|  |   } | |||
|  | ); | |||
|  | 
 | |||
|  | /** | |||
|  |  * 获取系统信息 | |||
|  |  * GET /api/system/info | |||
|  |  */ | |||
|  | router.get('/info', auth, async (req, res, next) => { | |||
|  |   try { | |||
|  |     // 检查管理员权限
 | |||
|  |     if (req.user.role !== 'admin') { | |||
|  |       return res.status(HTTP_STATUS.FORBIDDEN).json({ | |||
|  |         success: false, | |||
|  |         message: '权限不足' | |||
|  |       }); | |||
|  |     } | |||
|  | 
 | |||
|  |     const systemInfo = { | |||
|  |       version: '1.0.0', | |||
|  |       nodeVersion: process.version, | |||
|  |       platform: process.platform, | |||
|  |       uptime: process.uptime(), | |||
|  |       memoryUsage: process.memoryUsage(), | |||
|  |       timestamp: new Date().toISOString() | |||
|  |     }; | |||
|  | 
 | |||
|  |     res.json({ | |||
|  |       success: true, | |||
|  |       data: systemInfo | |||
|  |     }); | |||
|  |   } catch (error) { | |||
|  |     next(error); | |||
|  |   } | |||
|  | }); | |||
|  | 
 | |||
|  | /** | |||
|  |  * 获取维护模式状态(公开接口) | |||
|  |  * GET /api/system/maintenance-status | |||
|  |  */ | |||
|  | router.get('/maintenance-status', async (req, res, next) => { | |||
|  |   try { | |||
|  |     const db = getDB(); | |||
|  |      | |||
|  |     // 从系统设置表获取维护模式状态
 | |||
|  |     const [rows] = await db.execute( | |||
|  |       'SELECT setting_value FROM system_settings WHERE setting_key = ?', | |||
|  |       ['maintenance_mode'] | |||
|  |     ); | |||
|  |      | |||
|  |     const maintenanceMode = rows.length > 0 ? rows[0].setting_value === 'true' : false; | |||
|  |      | |||
|  |     res.json({ | |||
|  |       success: true, | |||
|  |       data: { | |||
|  |         maintenance_mode: maintenanceMode | |||
|  |       } | |||
|  |     }); | |||
|  |      | |||
|  |   } catch (error) { | |||
|  |     console.error('获取维护模式状态失败:', error); | |||
|  |     next(error); | |||
|  |   } | |||
|  | }); | |||
|  | 
 | |||
|  | /** | |||
|  |  * 获取维护模式状态(管理员接口) | |||
|  |  * GET /api/system/admin/maintenance-status | |||
|  |  */ | |||
|  | router.get('/admin/maintenance-status', auth, async (req, res, next) => { | |||
|  |   try { | |||
|  |     // 检查管理员权限
 | |||
|  |     if (req.user.role !== 'admin') { | |||
|  |       return res.status(403).json({ | |||
|  |         success: false, | |||
|  |         error: { | |||
|  |           code: 'FORBIDDEN', | |||
|  |           message: '权限不足' | |||
|  |         } | |||
|  |       }); | |||
|  |     } | |||
|  | 
 | |||
|  |     const db = getDB(); | |||
|  |      | |||
|  |     // 从系统设置表获取维护模式状态
 | |||
|  |     const [rows] = await db.execute( | |||
|  |       'SELECT setting_value FROM system_settings WHERE setting_key = ?', | |||
|  |       ['maintenance_mode'] | |||
|  |     ); | |||
|  |      | |||
|  |     const maintenanceMode = rows.length > 0 ? rows[0].setting_value === 'true' : false; | |||
|  |      | |||
|  |     res.json({ | |||
|  |       success: true, | |||
|  |       data: { | |||
|  |         maintenance_mode: maintenanceMode | |||
|  |       } | |||
|  |     }); | |||
|  |      | |||
|  |   } catch (error) { | |||
|  |     console.error('获取维护模式状态失败:', error); | |||
|  |     next(error); | |||
|  |   } | |||
|  | }); | |||
|  | 
 | |||
|  | /** | |||
|  |  * 切换维护模式 | |||
|  |  * POST /api/system/toggle-maintenance | |||
|  |  */ | |||
|  | router.post('/toggle-maintenance', auth, async (req, res, next) => { | |||
|  |   try { | |||
|  |     // 检查管理员权限
 | |||
|  |     if (req.user.role !== 'admin') { | |||
|  |       return res.status(403).json({ | |||
|  |         success: false, | |||
|  |         error: { | |||
|  |           code: 'FORBIDDEN', | |||
|  |           message: '权限不足' | |||
|  |         } | |||
|  |       }); | |||
|  |     } | |||
|  | 
 | |||
|  |     const { maintenance_mode } = req.body; | |||
|  |     const db = getDB(); | |||
|  |      | |||
|  |     // 更新或插入维护模式设置
 | |||
|  |     await db.execute( | |||
|  |       `INSERT INTO system_settings (setting_key, setting_value, updated_at) 
 | |||
|  |        VALUES ('maintenance_mode', ?, NOW())  | |||
|  |        ON DUPLICATE KEY UPDATE  | |||
|  |        setting_value = VALUES(setting_value),  | |||
|  |        updated_at = NOW()`,
 | |||
|  |       [maintenance_mode ? 'true' : 'false'] | |||
|  |     ); | |||
|  |      | |||
|  |     logger.info('Maintenance mode toggled', { | |||
|  |       userId: req.user.id, | |||
|  |       username: req.user.username, | |||
|  |       maintenanceMode: maintenance_mode | |||
|  |     }); | |||
|  |      | |||
|  |     res.json({ | |||
|  |       success: true, | |||
|  |       data: { | |||
|  |         maintenance_mode: maintenance_mode | |||
|  |       }, | |||
|  |       message: maintenance_mode ? '维护模式已开启' : '维护模式已关闭' | |||
|  |     }); | |||
|  |      | |||
|  |   } catch (error) { | |||
|  |     console.error('切换维护模式失败:', error); | |||
|  |     next(error); | |||
|  |   } | |||
|  | }); | |||
|  | 
 | |||
|  | module.exports = router; |