mirror of
https://github.com/patdelphi/suanming.git
synced 2026-02-28 05:33:11 +08:00
231 lines
4.9 KiB
JavaScript
231 lines
4.9 KiB
JavaScript
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; |