添加 IntelliJ IDEA 项目配置文件
This commit is contained in:
@@ -1,194 +1,186 @@
|
||||
const express = require('express')
|
||||
const bcrypt = require('bcryptjs')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const Joi = require('joi')
|
||||
const router = express.Router()
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const Joi = require('joi');
|
||||
const User = require('../models/User');
|
||||
const { generateToken, refreshToken, authenticateToken } = require('../middleware/auth');
|
||||
|
||||
// 模拟用户数据
|
||||
const users = [
|
||||
{
|
||||
id: 1,
|
||||
username: 'admin',
|
||||
email: 'admin@example.com',
|
||||
password: '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
role: 'admin',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
username: 'buyer',
|
||||
email: 'buyer@example.com',
|
||||
password: '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
role: 'buyer',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
username: 'trader',
|
||||
email: 'trader@example.com',
|
||||
password: '$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
role: 'trader',
|
||||
status: 'active'
|
||||
}
|
||||
]
|
||||
|
||||
// 登录参数验证
|
||||
// 验证schema
|
||||
const loginSchema = Joi.object({
|
||||
username: Joi.string().min(2).max(50).required(),
|
||||
password: Joi.string().min(6).max(100).required()
|
||||
})
|
||||
});
|
||||
|
||||
// 生成JWT token
|
||||
const generateToken = (user) => {
|
||||
return jwt.sign(
|
||||
{
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
role: user.role
|
||||
},
|
||||
process.env.JWT_SECRET || 'niumall-secret-key',
|
||||
{ expiresIn: process.env.JWT_EXPIRES_IN || '24h' }
|
||||
)
|
||||
}
|
||||
const passwordResetRequestSchema = Joi.object({
|
||||
phone: Joi.string().pattern(/^1[3-9]\d{9}$/).required()
|
||||
});
|
||||
|
||||
const passwordResetConfirmSchema = Joi.object({
|
||||
phone: Joi.string().pattern(/^1[3-9]\d{9}$/).required(),
|
||||
resetCode: Joi.string().required(),
|
||||
newPassword: Joi.string().min(6).max(100).required()
|
||||
});
|
||||
|
||||
const changePasswordSchema = Joi.object({
|
||||
oldPassword: Joi.string().required(),
|
||||
newPassword: Joi.string().min(6).max(100).required()
|
||||
});
|
||||
|
||||
// 用户登录
|
||||
router.post('/login', async (req, res) => {
|
||||
try {
|
||||
// 参数验证
|
||||
const { error, value } = loginSchema.validate(req.body)
|
||||
const { error, value } = loginSchema.validate(req.body);
|
||||
if (error) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '参数验证失败',
|
||||
details: error.details[0].message
|
||||
})
|
||||
errors: error.details.map(detail => detail.message)
|
||||
});
|
||||
}
|
||||
|
||||
const { username, password } = value
|
||||
|
||||
const { username, password } = value;
|
||||
|
||||
// 查找用户
|
||||
const user = users.find(u => u.username === username || u.email === username)
|
||||
const user = await User.findByLoginIdentifier(username);
|
||||
|
||||
if (!user) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
message: '用户名或密码错误'
|
||||
})
|
||||
message: '用户名或密码错误',
|
||||
code: 'INVALID_CREDENTIALS'
|
||||
});
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
const isPasswordValid = await bcrypt.compare(password, user.password)
|
||||
if (!isPasswordValid) {
|
||||
const isValidPassword = await user.validatePassword(password);
|
||||
if (!isValidPassword) {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
message: '用户名或密码错误'
|
||||
})
|
||||
message: '用户名或密码错误',
|
||||
code: 'INVALID_CREDENTIALS'
|
||||
});
|
||||
}
|
||||
|
||||
// 检查用户状态
|
||||
if (user.status !== 'active') {
|
||||
return res.status(403).json({
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
message: '账户已被禁用,请联系管理员'
|
||||
})
|
||||
message: '账号已被禁用,请联系管理员',
|
||||
code: 'ACCOUNT_DISABLED'
|
||||
});
|
||||
}
|
||||
|
||||
// 生成token
|
||||
const token = generateToken(user)
|
||||
// 更新登录信息
|
||||
await user.updateLoginInfo();
|
||||
|
||||
// 生成JWT token
|
||||
const tokens = generateToken(user);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: '登录成功',
|
||||
data: {
|
||||
access_token: token,
|
||||
token_type: 'Bearer',
|
||||
expires_in: 86400, // 24小时
|
||||
...tokens,
|
||||
user: {
|
||||
id: user.id,
|
||||
uuid: user.uuid,
|
||||
username: user.username,
|
||||
phone: user.phone,
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
status: user.status
|
||||
real_name: user.real_name,
|
||||
avatar_url: user.avatar_url,
|
||||
user_type: user.user_type,
|
||||
status: user.status,
|
||||
last_login_at: user.last_login_at,
|
||||
login_count: user.login_count
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('登录失败:', error)
|
||||
console.error('登录错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '登录失败,请稍后重试'
|
||||
})
|
||||
message: '登录失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// 获取当前用户信息
|
||||
router.get('/me', authenticateToken, (req, res) => {
|
||||
const user = users.find(u => u.id === req.user.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
// 获取用户信息
|
||||
router.get('/me', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
// req.user 已经通过中间件注入
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
id: req.user.id,
|
||||
uuid: req.user.uuid,
|
||||
username: req.user.username,
|
||||
phone: req.user.phone,
|
||||
email: req.user.email,
|
||||
real_name: req.user.real_name,
|
||||
avatar_url: req.user.avatar_url,
|
||||
user_type: req.user.user_type,
|
||||
status: req.user.status,
|
||||
last_login_at: req.user.last_login_at,
|
||||
login_count: req.user.login_count,
|
||||
created_at: req.user.created_at,
|
||||
updated_at: req.user.updated_at
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取用户信息错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '用户不存在'
|
||||
})
|
||||
message: '获取用户信息失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
user: {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
status: user.status
|
||||
},
|
||||
permissions: getUserPermissions(user.role)
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
// 用户登出
|
||||
router.post('/logout', authenticateToken, (req, res) => {
|
||||
// 在实际项目中,可以将token加入黑名单
|
||||
res.json({
|
||||
success: true,
|
||||
message: '登出成功'
|
||||
})
|
||||
})
|
||||
|
||||
// JWT token验证中间件
|
||||
function authenticateToken(req, res, next) {
|
||||
const authHeader = req.headers['authorization']
|
||||
const token = authHeader && authHeader.split(' ')[1]
|
||||
|
||||
if (!token) {
|
||||
return res.status(401).json({
|
||||
router.post('/logout', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
// TODO: 实际项目中可以将token加入黑名单或Redis
|
||||
res.json({
|
||||
success: true,
|
||||
message: '退出登录成功'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('退出登录错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '访问令牌缺失'
|
||||
})
|
||||
message: '退出登录失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jwt.verify(token, process.env.JWT_SECRET || 'niumall-secret-key', (err, user) => {
|
||||
if (err) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: '访问令牌无效或已过期'
|
||||
})
|
||||
}
|
||||
req.user = user
|
||||
next()
|
||||
})
|
||||
}
|
||||
// 刷新token
|
||||
router.post('/refresh', refreshToken);
|
||||
|
||||
// 获取用户权限
|
||||
function getUserPermissions(role) {
|
||||
const permissions = {
|
||||
admin: ['*'], // 管理员拥有所有权限
|
||||
buyer: ['order:read', 'order:create', 'order:update', 'supplier:read'],
|
||||
trader: ['order:read', 'order:update', 'supplier:read', 'supplier:create', 'supplier:update', 'transport:read'],
|
||||
supplier: ['order:read', 'quality:read', 'quality:create', 'quality:update'],
|
||||
driver: ['transport:read', 'transport:update']
|
||||
// 验证token有效性
|
||||
router.post('/verify', authenticateToken, (req, res) => {
|
||||
try {
|
||||
// 如果通过认证中间件,说明token有效
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Token有效',
|
||||
data: {
|
||||
valid: true,
|
||||
user: {
|
||||
id: req.user.id,
|
||||
username: req.user.username,
|
||||
user_type: req.user.user_type
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Token验证错误:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: 'Token验证失败',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
|
||||
return permissions[role] || []
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user