Files
suanming/server/routes/auth.js

231 lines
4.9 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.
import express from 'express';
import { authService } from '../services/authService.js';
import { authenticateToken, rateLimit } from '../middleware/auth.js';
const router = express.Router();
// 应用速率限制
router.use(rateLimit({ max: 20, windowMs: 15 * 60 * 1000 })); // 15分钟内最多20次请求
/**
* 用户注册
* POST /api/auth/signup
*/
router.post('/signup', async (req, res, next) => {
try {
const { email, password, fullName, birthDate, birthTime, birthPlace, gender } = req.body;
// 基本验证
if (!email || !password) {
return res.status(400).json({
error: {
code: 'MISSING_PARAMETERS',
message: '邮箱和密码不能为空'
}
});
}
// 邮箱格式验证
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return res.status(400).json({
error: {
code: 'INVALID_EMAIL',
message: '邮箱格式不正确'
}
});
}
// 密码强度验证
if (password.length < 6) {
return res.status(400).json({
error: {
code: 'WEAK_PASSWORD',
message: '密码长度至少6位'
}
});
}
const result = await authService.signUp({
email,
password,
fullName,
birthDate,
birthTime,
birthPlace,
gender
});
res.status(201).json({
data: result,
message: '注册成功'
});
} catch (error) {
next(error);
}
});
/**
* 用户登录
* POST /api/auth/signin
*/
router.post('/signin', async (req, res, next) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({
error: {
code: 'MISSING_PARAMETERS',
message: '邮箱和密码不能为空'
}
});
}
const result = await authService.signIn(email, password);
res.json({
data: result,
message: '登录成功'
});
} catch (error) {
if (error.message.includes('邮箱或密码错误')) {
return res.status(401).json({
error: {
code: 'INVALID_CREDENTIALS',
message: error.message
}
});
}
next(error);
}
});
/**
* 获取当前用户信息
* GET /api/auth/user
*/
router.get('/user', authenticateToken, async (req, res, next) => {
try {
const user = await authService.getUserById(req.user.userId);
res.json({
data: { user },
message: '获取用户信息成功'
});
} catch (error) {
next(error);
}
});
/**
* 更新用户信息
* PUT /api/auth/user
*/
router.put('/user', authenticateToken, async (req, res, next) => {
try {
const { fullName, birthDate, birthTime, birthPlace, gender } = req.body;
const updatedUser = await authService.updateUser(req.user.userId, {
fullName,
birthDate,
birthTime,
birthPlace,
gender
});
res.json({
data: { user: updatedUser },
message: '用户信息更新成功'
});
} catch (error) {
next(error);
}
});
/**
* 验证token
* POST /api/auth/verify
*/
router.post('/verify', async (req, res, next) => {
try {
const { token } = req.body;
if (!token) {
return res.status(400).json({
error: {
code: 'MISSING_TOKEN',
message: 'Token不能为空'
}
});
}
const decoded = authService.verifyToken(token);
const user = await authService.getUserById(decoded.userId);
res.json({
data: { user, valid: true },
message: 'Token验证成功'
});
} catch (error) {
res.status(401).json({
error: {
code: 'INVALID_TOKEN',
message: 'Token无效或已过期'
}
});
}
});
/**
* 用户登出(客户端处理,服务端记录日志)
* POST /api/auth/signout
*/
router.post('/signout', authenticateToken, async (req, res) => {
try {
// 这里可以添加登出日志记录
console.log(`用户 ${req.user.userId}${new Date().toISOString()} 登出`);
res.json({
message: '登出成功'
});
} catch (error) {
res.status(500).json({
error: {
code: 'SIGNOUT_ERROR',
message: '登出失败'
}
});
}
});
/**
* 刷新token可选功能
* POST /api/auth/refresh
*/
router.post('/refresh', authenticateToken, async (req, res, next) => {
try {
const user = await authService.getUserById(req.user.userId);
// 生成新的token
const jwt = await import('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET || 'your-super-secret-jwt-key-change-in-production';
const newToken = jwt.default.sign(
{ userId: user.id, email: user.email },
JWT_SECRET,
{ expiresIn: '7d' }
);
res.json({
data: {
user,
token: newToken
},
message: 'Token刷新成功'
});
} catch (error) {
next(error);
}
});
export default router;