|
|
@@ -6,81 +6,166 @@ const router = express.Router();
|
|
|
const authMiddleware = require('../middleware/authMiddleware');
|
|
|
|
|
|
const User = require('../models/User');
|
|
|
+const Logs = require('../libs/logs');
|
|
|
|
|
|
// 注册
|
|
|
router.post('/register', async (req, res) => {
|
|
|
const { username, password } = req.body;
|
|
|
- try {
|
|
|
- const existing = await User.findOne({ username });
|
|
|
+ User.findOne({ username })
|
|
|
+ .then(existing => {
|
|
|
if (existing) {
|
|
|
- return res.badRequest('用户已存在');
|
|
|
+ return Promise.reject(new Error('USER_EXISTS'));
|
|
|
}
|
|
|
-
|
|
|
- const hashedPassword = await bcrypt.hash(password, 10);
|
|
|
+ return bcrypt.hash(password, 10);
|
|
|
+ })
|
|
|
+ .then(hashedPassword => {
|
|
|
const user = new User({ username, password: hashedPassword });
|
|
|
- await user.save();
|
|
|
+ return user.save();
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
res.sendSuccess('注册成功');
|
|
|
- }
|
|
|
- catch (err) {
|
|
|
- res.serverError();
|
|
|
- }
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ Logs.errDev('注册失败:', err);
|
|
|
+ if (err.message === 'USER_EXISTS') {
|
|
|
+ return res.badRequest('用户已存在');
|
|
|
+ }
|
|
|
+ res.badRequest(err.message);
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
-// 登录
|
|
|
+// 登录 - 支持原路径 /login 和 mock 服务路径 /login
|
|
|
router.post('/login', async (req, res) => {
|
|
|
const { username, password } = req.body;
|
|
|
- try {
|
|
|
- const user = await User.findOne({ username });
|
|
|
+ User.findOne({ username })
|
|
|
+ .then(user => {
|
|
|
if (!user) {
|
|
|
- return res.badRequest('用户不存在');
|
|
|
+ return Promise.reject(new Error('USER_NOT_FOUND'));
|
|
|
}
|
|
|
-
|
|
|
- const isMatch = await bcrypt.compare(password, user.password);
|
|
|
+ return Promise.all([
|
|
|
+ bcrypt.compare(password, user.password),
|
|
|
+ Promise.resolve(user),
|
|
|
+ ]);
|
|
|
+ })
|
|
|
+ .then(([isMatch, user]) => {
|
|
|
if (!isMatch) {
|
|
|
- return res.badRequest('密码错误');
|
|
|
+ return Promise.reject(new Error('PASSWORD_ERROR'));
|
|
|
}
|
|
|
-
|
|
|
+ return user;
|
|
|
+ })
|
|
|
+ .then(user => {
|
|
|
// 签发 Access Token 和 Refresh Token
|
|
|
- const accessToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
|
|
|
+ const accessToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '30m' });
|
|
|
const refreshToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' });
|
|
|
|
|
|
- res.json({ access_token: accessToken, refresh_token: refreshToken });
|
|
|
- }
|
|
|
- catch (err) {
|
|
|
- res.serverError();
|
|
|
- }
|
|
|
+ // 设置 refresh token 到 cookie
|
|
|
+ res.cookie('jwt', refreshToken, {
|
|
|
+ httpOnly: true,
|
|
|
+ secure: true,
|
|
|
+ sameSite: 'none',
|
|
|
+ maxAge: 7 * 24 * 60 * 60 * 1000 // 7天
|
|
|
+ });
|
|
|
+
|
|
|
+ // 返回格式与前端期望一致
|
|
|
+ res.sendSuccess({
|
|
|
+ accessToken: accessToken,
|
|
|
+ uid: user._id.toString(),
|
|
|
+ username: user.username,
|
|
|
+ roles: user.roles ?? ['user'],
|
|
|
+ });
|
|
|
+
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ Logs.errDev('登录失败:', err);
|
|
|
+ if (err.message === 'USER_NOT_FOUND') {
|
|
|
+ return res.badRequest('用户不存在');
|
|
|
+ }
|
|
|
+ if (err.message === 'PASSWORD_ERROR') {
|
|
|
+ return res.badRequest('密码错误');
|
|
|
+ }
|
|
|
+ res.badRequest(err.message);
|
|
|
+ });
|
|
|
+
|
|
|
});
|
|
|
|
|
|
-// 刷新 Token
|
|
|
-router.post('/refresh_token', async (req, res) => {
|
|
|
- const { refreshToken } = req.body;
|
|
|
+// 刷新 Token - 支持 Vben Admin 的 /refresh 路径
|
|
|
+router.post('/refresh', async (req, res) => {
|
|
|
+ const refreshToken = req.cookies.jwt;
|
|
|
|
|
|
if (!refreshToken) {
|
|
|
- return res.unauthorized('无效的 "refresh token"');
|
|
|
+ return res.unauthorized('无效的刷新token');
|
|
|
}
|
|
|
-
|
|
|
- try {
|
|
|
- // 验证 Refresh Token
|
|
|
- const decoded = jwt.verify(refreshToken, process.env.JWT_SECRET);
|
|
|
- const user = await User.findById(decoded.userId);
|
|
|
+ const decoded = jwt.verify(refreshToken, process.env.JWT_SECRET);
|
|
|
+ User.findById(decoded.userId)
|
|
|
+ .then(user => {
|
|
|
if (!user) {
|
|
|
- return res.unauthorized('用户不存在');
|
|
|
+ return Promise.reject(new Error('USER_NOT_FOUND'));
|
|
|
}
|
|
|
|
|
|
// 签发新的 Access Token
|
|
|
- const newAccessToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
|
|
|
+ const newAccessToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '30m' });
|
|
|
+
|
|
|
+ // 按照Vben Admin期望的格式返回
|
|
|
+ res.send(newAccessToken);
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ Logs.errDev('刷新Token失败:', err);
|
|
|
+ res.clearCookie('jwt');
|
|
|
+ if (err.message === 'USER_NOT_FOUND') {
|
|
|
+ return res.unauthorized('用户不存在');
|
|
|
+ }
|
|
|
+ res.unauthorized(err.message);
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
|
|
|
- res.json({ access_token: newAccessToken });
|
|
|
+// 用户信息 - 支持 mock 服务的 /info 路径
|
|
|
+router.get('/info', authMiddleware, async (req, res) => {
|
|
|
+ User.findById(req.userId).select('-password')
|
|
|
+ .then(user => {
|
|
|
+ if (!user) {
|
|
|
+ return Promise.reject(new Error('USER_NOT_FOUND'));
|
|
|
+ }
|
|
|
+
|
|
|
+ const userInfo = {
|
|
|
+ uid: user._id.toString(),
|
|
|
+ username: user.username,
|
|
|
+ roles: user.roles ?? ['user'],
|
|
|
+ };
|
|
|
+
|
|
|
+ res.sendSuccess(userInfo);
|
|
|
+
|
|
|
+ })
|
|
|
+ .catch(err => {
|
|
|
+ Logs.errDev('获取用户信息错误:', err);
|
|
|
+ if (err.message === 'USER_NOT_FOUND') {
|
|
|
+ return res.notFound('用户不存在');
|
|
|
+ }
|
|
|
+ res.serverError(err.message);
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+// 权限码 - 支持 mock 服务的 /codes 路径
|
|
|
+router.get('/codes', authMiddleware, async (req, res) => {
|
|
|
+ try {
|
|
|
+ // 返回所有功能的权限码
|
|
|
+ const codes = [
|
|
|
+ 'dashboard',
|
|
|
+ 'dashboard:analysis',
|
|
|
+ 'dashboard:workbench',
|
|
|
+ 'system',
|
|
|
+ 'system:account',
|
|
|
+ 'system:account:settings',
|
|
|
+ 'system:role',
|
|
|
+ 'system:menu',
|
|
|
+ 'system:dept',
|
|
|
+ ];
|
|
|
+ res.sendSuccess(codes);
|
|
|
}
|
|
|
catch (err) {
|
|
|
- res.unauthorized('无效或已过期的 "refresh token"');
|
|
|
+ Logs.errDev('获取权限码错误:', err);
|
|
|
+ res.serverError(err.message);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-// 受保护接口
|
|
|
-// router.get('/profile', authMiddleware, async (req, res) => {
|
|
|
-// const user = await User.findById(req.userId).select('-password');
|
|
|
-// res.json(user);
|
|
|
-// });
|
|
|
-
|
|
|
module.exports = router;
|