Files
nxxmdata/government-backend/controllers/authController.js

211 lines
5.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const jwt = require('jsonwebtoken');
const User = require('../models/User');
const AdminStaff = require('../models/AdminStaff');
const bcrypt = require('bcryptjs');
const jwtModule = require('jsonwebtoken');
const tokenBlacklist = require('../utils/tokenBlacklist');
// JWT配置
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
exports.login = async (req, res) => {
try {
const { username, password } = req.body;
// 从数据库查找用户
const user = await User.findOne({
where: {
username,
status: 'active'
}
});
if (!user) {
return res.status(401).json({
code: 401,
message: '用户名或密码错误'
});
}
// 验证密码
const isPasswordValid = await bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(401).json({
code: 401,
message: '用户名或密码错误'
});
}
// 更新最后登录时间
await user.update({
last_login: new Date()
});
const token = jwtModule.sign({
id: user.id,
username: user.username,
role: user.role
}, JWT_SECRET, { expiresIn: '2h' });
return res.json({
code: 200,
message: '登录成功',
data: { token }
});
} catch (err) {
console.error('登录错误:', err);
res.status(500).json({
code: 500,
message: '服务器错误',
error: err.message
});
}
}
// 获取用户信息
exports.getUserInfo = async (req, res) => {
try {
// 从token中解析用户信息
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({
code: 401,
message: '未提供认证令牌'
});
}
try {
// 先检查token是否在黑名单中
if (tokenBlacklist.isBlacklisted(token)) {
return res.status(401).json({
code: 401,
message: '认证令牌已失效(已退出登录)'
});
}
const decoded = jwtModule.verify(token, JWT_SECRET);
// 从数据库获取用户信息
const user = await User.findByPk(decoded.id);
if (!user || user.status !== 'active') {
return res.status(401).json({
code: 401,
message: '用户不存在或已禁用'
});
}
// 获取员工信息
let staffInfo = null;
try {
staffInfo = await AdminStaff.findOne({
where: {
phone: user.username
}
});
} catch (error) {
console.warn('获取员工信息失败:', error);
}
// 根据角色设置权限
const permissions = getPermissionsByRole(user.role);
const userInfo = {
id: user.id,
username: user.username,
name: staffInfo?.name || user.username,
role: user.role,
avatar: '',
email: '',
phone: staffInfo?.phone || user.username,
department: staffInfo?.department_id ? {
id: staffInfo.department_id,
name: ''
} : null,
position: staffInfo?.position_id ? {
id: staffInfo.position_id,
name: ''
} : null,
permissions
};
return res.json({
code: 200,
message: '获取用户信息成功',
data: userInfo
});
} catch (jwtError) {
console.error('JWT验证错误:', jwtError);
return res.status(401).json({
code: 401,
message: '认证令牌无效'
});
}
} catch (err) {
console.error('获取用户信息错误:', err);
res.status(500).json({
code: 500,
message: '服务器错误',
error: err.message
});
}
};
// 根据角色获取权限
function getPermissionsByRole(role) {
const basePermissions = ['dashboard'];
switch (role) {
case 'admin':
return [...basePermissions, 'users', 'settings', 'supervision', 'approval', 'personnel', 'warehouse', 'epidemic', 'service', 'visualization'];
case 'manager':
return [...basePermissions, 'supervision', 'approval', 'personnel', 'warehouse', 'epidemic', 'service'];
case 'inspector':
return [...basePermissions, 'supervision', 'epidemic'];
case 'clerk':
return [...basePermissions, 'approval', 'personnel', 'warehouse', 'service'];
default:
return basePermissions;
}
};
// 退出登录
exports.logout = async (req, res) => {
try {
// 从请求头中获取token
const token = req.headers.authorization?.replace('Bearer ', '');
if (token) {
try {
// 解码token获取过期时间
const decoded = jwtModule.decode(token);
if (decoded && decoded.exp) {
// 计算token剩余有效期毫秒
const currentTime = Math.floor(Date.now() / 1000);
const expiresIn = (decoded.exp - currentTime) * 1000;
if (expiresIn > 0) {
// 将token添加到黑名单
tokenBlacklist.addToBlacklist(token, expiresIn);
console.log(`用户退出登录token已添加到黑名单: ${token.substring(0, 20)}...`);
}
}
} catch (decodeError) {
console.warn('解码token失败:', decodeError);
}
}
return res.json({
code: 200,
message: '退出登录成功'
});
} catch (err) {
console.error('退出登录错误:', err);
res.status(500).json({
code: 500,
message: '服务器错误',
error: err.message
});
}
};