Files
2026-02-12 11:09:43 +08:00

268 lines
7.1 KiB
JavaScript

const express = require('express');
const bcrypt = require('bcryptjs');
const db = require('../config/database');
const { authenticateToken } = require('../middleware/auth');
const router = express.Router();
// 所有路由都需要认证
router.use(authenticateToken);
// 管理员权限中间件
const requireAdmin = (req, res, next) => {
if (!req.user || !req.user.isAdmin) {
return res.status(403).json({ error: '需要管理员权限' });
}
next();
};
// 获取所有用户列表(管理员)
router.get('/', requireAdmin, async (req, res) => {
try {
const [users] = await db.pool.execute(`
SELECT
id, email, phone, is_admin, is_active,
last_login, created_at, updated_at,
(SELECT COUNT(*) FROM servers WHERE user_id = users.id) as server_count
FROM users
ORDER BY created_at DESC
`);
res.json({ users });
} catch (error) {
console.error('获取用户列表错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 获取单个用户详细信息(管理员)
router.get('/:id', requireAdmin, async (req, res) => {
try {
const { id } = req.params;
// 获取用户基本信息
const [users] = await db.pool.execute(
'SELECT id, email, phone, is_admin, is_active, last_login, created_at, updated_at FROM users WHERE id = ?',
[id]
);
if (users.length === 0) {
return res.status(404).json({ error: '用户不存在' });
}
const user = users[0];
// 获取用户的服务器列表
const [servers] = await db.pool.execute(`
SELECT
id, name, host, port, username, auth_type,
group_name, created_at, updated_at
FROM servers
WHERE user_id = ?
ORDER BY created_at DESC
`, [id]);
// 获取用户的连接日志统计
const [connectionStats] = await db.pool.execute(`
SELECT
COUNT(*) as total_connections,
SUM(duration) as total_duration,
MAX(start_time) as last_connection
FROM connection_logs
WHERE user_id = ?
`, [id]);
res.json({
user: {
...user,
server_count: servers.length,
connection_stats: connectionStats[0]
},
servers
});
} catch (error) {
console.error('获取用户详情错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 创建新用户(管理员)
router.post('/', requireAdmin, async (req, res) => {
try {
const { email, phone, password, is_admin = false } = req.body;
// 验证输入
if (!email || !password) {
return res.status(400).json({ error: '邮箱和密码是必填项' });
}
if (password.length < 6) {
return res.status(400).json({ error: '密码长度至少6位' });
}
// 检查用户是否已存在
const [existingUsers] = await db.pool.execute(
'SELECT id FROM users WHERE email = ?',
[email]
);
if (existingUsers.length > 0) {
return res.status(400).json({ error: '该邮箱已被注册' });
}
// 加密密码
const saltRounds = 12;
const passwordHash = await bcrypt.hash(password, saltRounds);
// 创建用户
const [result] = await db.pool.execute(
'INSERT INTO users (email, phone, password_hash, is_admin) VALUES (?, ?, ?, ?)',
[email, phone || null, passwordHash, is_admin ? 1 : 0]
);
res.status(201).json({
message: '用户创建成功',
user: {
id: result.insertId,
email,
phone,
is_admin: is_admin ? 1 : 0
}
});
} catch (error) {
console.error('创建用户错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 更新用户信息(管理员)
router.put('/:id', requireAdmin, async (req, res) => {
try {
const { id } = req.params;
const { email, phone, is_admin, is_active } = req.body;
// 检查用户是否存在
const [users] = await db.pool.execute(
'SELECT id FROM users WHERE id = ?',
[id]
);
if (users.length === 0) {
return res.status(404).json({ error: '用户不存在' });
}
// 构建更新字段
const updateFields = [];
const updateValues = [];
if (email !== undefined) {
updateFields.push('email = ?');
updateValues.push(email);
}
if (phone !== undefined) {
updateFields.push('phone = ?');
updateValues.push(phone);
}
if (is_admin !== undefined) {
updateFields.push('is_admin = ?');
updateValues.push(is_admin ? 1 : 0);
}
if (is_active !== undefined) {
updateFields.push('is_active = ?');
updateValues.push(is_active ? 1 : 0);
}
if (updateFields.length === 0) {
return res.status(400).json({ error: '没有需要更新的字段' });
}
updateValues.push(id);
// 更新用户信息
await db.pool.execute(
`UPDATE users SET ${updateFields.join(', ')} WHERE id = ?`,
updateValues
);
res.json({ message: '用户信息更新成功' });
} catch (error) {
console.error('更新用户信息错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 重置用户密码(管理员)
router.put('/:id/password', requireAdmin, async (req, res) => {
try {
const { id } = req.params;
const { newPassword } = req.body;
if (!newPassword) {
return res.status(400).json({ error: '新密码是必填项' });
}
if (newPassword.length < 6) {
return res.status(400).json({ error: '密码长度至少6位' });
}
// 检查用户是否存在
const [users] = await db.pool.execute(
'SELECT id FROM users WHERE id = ?',
[id]
);
if (users.length === 0) {
return res.status(404).json({ error: '用户不存在' });
}
// 加密新密码
const saltRounds = 12;
const newPasswordHash = await bcrypt.hash(newPassword, saltRounds);
// 更新密码
await db.pool.execute(
'UPDATE users SET password_hash = ? WHERE id = ?',
[newPasswordHash, id]
);
res.json({ message: '密码重置成功' });
} catch (error) {
console.error('重置密码错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 删除用户(管理员)
router.delete('/:id', requireAdmin, async (req, res) => {
try {
const { id } = req.params;
// 检查用户是否存在
const [users] = await db.pool.execute(
'SELECT id FROM users WHERE id = ?',
[id]
);
if (users.length === 0) {
return res.status(404).json({ error: '用户不存在' });
}
// 检查是否为管理员自身(不允许删除自己)
if (parseInt(id) === parseInt(req.user.userId)) {
return res.status(400).json({ error: '不能删除自己的账户' });
}
// 删除用户(由于外键约束,关联的服务器和分组也会被删除)
await db.pool.execute('DELETE FROM users WHERE id = ?', [id]);
res.json({ message: '用户删除成功' });
} catch (error) {
console.error('删除用户错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
module.exports = router;