user.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. router.post('/logout', authMiddleware, (req, res) => {
  83. res.clearCookie('jwt');
  84. res.sendSuccess('退出成功');
  85. });
  86. // 刷新 Token - 支持 Vben Admin 的 /refresh 路径
  87. router.post('/refresh', async (req, res) => {
  88. const refreshToken = req.cookies.jwt;
  89. if (!refreshToken) {
  90. return res.unauthorized('无效的刷新token');
  91. }
  92. const decoded = jwt.verify(refreshToken, process.env.JWT_SECRET);
  93. User.findById(decoded.userId)
  94. .then(user => {
  95. if (!user) {
  96. return Promise.reject(new Error('USER_NOT_FOUND'));
  97. }
  98. // 签发新的 Access Token
  99. const newAccessToken = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '30m' });
  100. // 按照Vben Admin期望的格式返回
  101. res.send(newAccessToken);
  102. })
  103. .catch(err => {
  104. Logs.errDev('刷新Token失败:', err);
  105. res.clearCookie('jwt');
  106. if (err.message === 'USER_NOT_FOUND') {
  107. return res.unauthorized('用户不存在');
  108. }
  109. res.unauthorized(err.message);
  110. });
  111. });
  112. // 用户信息 - 支持 mock 服务的 /info 路径
  113. router.get('/info', authMiddleware, async (req, res) => {
  114. User.findById(req.userId).select('-password')
  115. .then(user => {
  116. if (!user) {
  117. return Promise.reject(new Error('USER_NOT_FOUND'));
  118. }
  119. const userInfo = {
  120. uid: user._id.toString(),
  121. username: user.username,
  122. roles: user.roles ?? ['user'],
  123. };
  124. res.sendSuccess(userInfo);
  125. })
  126. .catch(err => {
  127. Logs.errDev('获取用户信息错误:', err);
  128. if (err.message === 'USER_NOT_FOUND') {
  129. return res.notFound('用户不存在');
  130. }
  131. res.serverError(err.message);
  132. });
  133. });
  134. // 权限码 - 支持 mock 服务的 /codes 路径
  135. router.get('/codes', authMiddleware, async (req, res) => {
  136. try {
  137. // 返回所有功能的权限码
  138. const codes = [
  139. 'dashboard',
  140. 'dashboard:analysis',
  141. 'dashboard:workbench',
  142. 'system',
  143. 'system:account',
  144. 'system:account:settings',
  145. 'system:role',
  146. 'system:menu',
  147. 'system:dept',
  148. ];
  149. res.sendSuccess(codes);
  150. }
  151. catch (err) {
  152. Logs.errDev('获取权限码错误:', err);
  153. res.serverError(err.message);
  154. }
  155. });
  156. module.exports = router;