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; |