first commit

This commit is contained in:
2025-09-23 07:35:11 +00:00
commit a5dd3f1335
110 changed files with 46108 additions and 0 deletions

249
api/routes/auth.ts Executable file
View File

@@ -0,0 +1,249 @@
/**
* This is a user authentication API route.
* Handle user registration, login, token management, etc.
*/
import { Router, type Request, type Response } from 'express';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { query, queryOne, execute } from '../config/database.js';
const router = Router();
// JWT密钥
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
/**
* User Registration
* POST /api/auth/register
*/
router.post('/register', async (req: Request, res: Response): Promise<void> => {
try {
const { username, email, password } = req.body;
// 验证输入
if (!username || !email || !password) {
res.status(400).json({
success: false,
message: '用户名、邮箱和密码都是必填项'
});
return;
}
// 检查用户是否已存在
const existingUser = await queryOne(
'SELECT id FROM users WHERE username = ? OR email = ?',
[username, email]
);
if (existingUser) {
res.status(400).json({
success: false,
message: '用户名或邮箱已存在'
});
return;
}
// 加密密码
const hashedPassword = await bcrypt.hash(password, 10);
// 插入新用户
const result = await execute(
'INSERT INTO users (username, email, password, created_at) VALUES (?, ?, ?, datetime("now"))',
[username, email, hashedPassword]
);
res.status(201).json({
success: true,
message: '用户注册成功',
data: {
id: result.lastID,
username,
email
}
});
} catch (error) {
console.error('注册失败:', error);
res.status(500).json({
success: false,
message: '服务器内部错误'
});
}
});
/**
* User Login
* POST /api/auth/login
*/
router.post('/login', async (req: Request, res: Response): Promise<void> => {
try {
const { username, password } = req.body;
// 验证输入
if (!username || !password) {
res.status(400).json({
success: false,
message: '用户名和密码都是必填项'
});
return;
}
// 查找用户
const user = await queryOne(
'SELECT id, username, email, password, role FROM users WHERE username = ? OR email = ?',
[username, username]
);
if (!user) {
res.status(401).json({
success: false,
message: '用户名或密码错误'
});
return;
}
// 验证密码
const isValidPassword = await bcrypt.compare(password, user.password);
if (!isValidPassword) {
res.status(401).json({
success: false,
message: '用户名或密码错误'
});
return;
}
// 生成JWT token
const token = jwt.sign(
{
id: user.id,
username: user.username,
email: user.email,
role: user.role
},
JWT_SECRET,
{ expiresIn: '24h' }
);
res.json({
success: true,
message: '登录成功',
data: {
token,
user: {
id: user.id,
username: user.username,
email: user.email,
role: user.role
}
}
});
} catch (error) {
console.error('登录失败:', error);
res.status(500).json({
success: false,
message: '服务器内部错误'
});
}
});
/**
* Token Refresh
* POST /api/auth/refresh
*/
router.post('/refresh', async (req: Request, res: Response): Promise<void> => {
try {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
res.status(401).json({
success: false,
message: '访问令牌缺失'
});
return;
}
// 验证当前token即使过期也要能解析出用户信息
let decoded: any;
try {
decoded = jwt.verify(token, JWT_SECRET);
} catch (error: any) {
// 如果是过期错误尝试解析过期的token
if (error.name === 'TokenExpiredError') {
decoded = jwt.decode(token);
if (!decoded) {
res.status(401).json({
success: false,
message: '无效的访问令牌'
});
return;
}
} else {
res.status(401).json({
success: false,
message: '无效的访问令牌'
});
return;
}
}
// 验证用户是否仍然存在
const user = await queryOne(
'SELECT id, username, email, role FROM users WHERE id = ?',
[decoded.id]
);
if (!user) {
res.status(401).json({
success: false,
message: '用户不存在'
});
return;
}
// 生成新的JWT token
const newToken = jwt.sign(
{
id: user.id,
username: user.username,
email: user.email,
role: user.role
},
JWT_SECRET,
{ expiresIn: '24h' }
);
res.json({
success: true,
message: 'Token刷新成功',
data: {
token: newToken,
user: {
id: user.id,
username: user.username,
email: user.email,
role: user.role
}
}
});
} catch (error) {
console.error('Token刷新失败:', error);
res.status(500).json({
success: false,
message: '服务器内部错误'
});
}
});
/**
* User Logout
* POST /api/auth/logout
*/
router.post('/logout', async (req: Request, res: Response): Promise<void> => {
// 由于使用JWTlogout主要在前端处理删除token
res.json({
success: true,
message: '退出登录成功'
});
});
export default router;