user.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. const express = require('express');
  2. const bcrypt = require('bcryptjs');
  3. const jwt = require('jsonwebtoken');
  4. const router = express.Router();
  5. const authMiddleware = require('../middleware/authMiddleware');
  6. const User = require('../models/User');
  7. const Logs = require('../libs/logs');
  8. // 注册
  9. router.post('/register', async (req, res) => {
  10. const { username, password } = req.body;
  11. User.findOne({ username })
  12. .then(existing => {
  13. if (existing) {
  14. return Promise.reject(new Error('USER_EXISTS'));
  15. }
  16. return bcrypt.hash(password, 10);
  17. })
  18. .then(hashedPassword => {
  19. const user = new User({ username, password: hashedPassword });
  20. return user.save();
  21. })
  22. .then(() => {
  23. res.sendSuccess('注册成功');
  24. })
  25. .catch(err => {
  26. Logs.errDev('注册失败:', err);
  27. if (err.message === 'USER_EXISTS') {
  28. return res.badRequest('用户已存在');
  29. }
  30. res.badRequest(err.message);
  31. });
  32. });
  33. // 登录 - 支持原路径 /login 和 mock 服务路径 /login
  34. router.post('/login', async (req, res) => {
  35. const { username, password } = req.body;
  36. User.findOne({ username })
  37. .then(user => {
  38. if (!user) {
  39. return Promise.reject(new Error('USER_NOT_FOUND'));
  40. }
  41. return Promise.all([
  42. bcrypt.compare(password, user.password),
  43. Promise.resolve(user),
  44. ]);
  45. })
  46. .then(([isMatch, user]) => {
  47. if (!isMatch) {
  48. return Promise.reject(new Error('PASSWORD_ERROR'));
  49. }
  50. return user;
  51. })
  52. .then(user => {
  53. // 签发 Access Token 和 Refresh Token
  54. const accessToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '30m' });
  55. const refreshToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' });
  56. // 设置 refresh token 到 cookie
  57. res.cookie('jwt', refreshToken, {
  58. httpOnly: true,
  59. secure: true,
  60. sameSite: 'none',
  61. maxAge: 7 * 24 * 60 * 60 * 1000 // 7天
  62. });
  63. // 返回格式与前端期望一致
  64. res.sendSuccess({
  65. accessToken: accessToken,
  66. uid: user._id.toString(),
  67. username: user.username,
  68. roles: user.roles ?? ['user'],
  69. });
  70. })
  71. .catch(err => {
  72. Logs.errDev('登录失败:', err);
  73. if (err.message === 'USER_NOT_FOUND') {
  74. return res.badRequest('用户不存在');
  75. }
  76. if (err.message === 'PASSWORD_ERROR') {
  77. return res.badRequest('密码错误');
  78. }
  79. res.badRequest(err.message);
  80. });
  81. });
  82. // 刷新 Token - 支持 Vben Admin 的 /refresh 路径
  83. router.post('/refresh', async (req, res) => {
  84. const refreshToken = req.cookies.jwt;
  85. if (!refreshToken) {
  86. return res.unauthorized('无效的刷新token');
  87. }
  88. const decoded = jwt.verify(refreshToken, process.env.JWT_SECRET);
  89. User.findById(decoded.userId)
  90. .then(user => {
  91. if (!user) {
  92. return Promise.reject(new Error('USER_NOT_FOUND'));
  93. }
  94. // 签发新的 Access Token
  95. const newAccessToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '30m' });
  96. // 按照Vben Admin期望的格式返回
  97. res.send(newAccessToken);
  98. })
  99. .catch(err => {
  100. Logs.errDev('刷新Token失败:', err);
  101. res.clearCookie('jwt');
  102. if (err.message === 'USER_NOT_FOUND') {
  103. return res.unauthorized('用户不存在');
  104. }
  105. res.unauthorized(err.message);
  106. });
  107. });
  108. // 用户信息 - 支持 mock 服务的 /info 路径
  109. router.get('/info', authMiddleware, async (req, res) => {
  110. User.findById(req.userId).select('-password')
  111. .then(user => {
  112. if (!user) {
  113. return Promise.reject(new Error('USER_NOT_FOUND'));
  114. }
  115. const userInfo = {
  116. uid: user._id.toString(),
  117. username: user.username,
  118. roles: user.roles ?? ['user'],
  119. };
  120. res.sendSuccess(userInfo);
  121. })
  122. .catch(err => {
  123. Logs.errDev('获取用户信息错误:', err);
  124. if (err.message === 'USER_NOT_FOUND') {
  125. return res.notFound('用户不存在');
  126. }
  127. res.serverError(err.message);
  128. });
  129. });
  130. // 权限码 - 支持 mock 服务的 /codes 路径
  131. router.get('/codes', authMiddleware, async (req, res) => {
  132. try {
  133. // 返回所有功能的权限码
  134. const codes = [
  135. 'dashboard',
  136. 'dashboard:analysis',
  137. 'dashboard:workbench',
  138. 'system',
  139. 'system:account',
  140. 'system:account:settings',
  141. 'system:role',
  142. 'system:menu',
  143. 'system:dept',
  144. ];
  145. res.sendSuccess(codes);
  146. }
  147. catch (err) {
  148. Logs.errDev('获取权限码错误:', err);
  149. res.serverError(err.message);
  150. }
  151. });
  152. module.exports = router;