You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

353 lines
8.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 认证控制器
*
* 功能:处理用户注册、登录、获取信息等认证相关的业务逻辑
*
* 说明Controller层处理业务逻辑调用Model层操作数据库
*/
const User = require('../models/User');
const { hashPassword, comparePassword, generateToken } = require('../utils/encryption');
const {
validateRequired,
validateUsername,
validatePassword,
validateEmail,
validateBatch
} = require('../utils/validator');
const { success, error } = require('../utils/response');
const { BusinessError, ValidationError } = require('../middleware/errorHandler');
/**
* 用户注册
* POST /api/auth/register
*/
const register = async (req, res, next) => {
try {
const { username, password, real_name, phone, email, role } = req.body;
// 数据验证
const validation = validateBatch([
validateRequired(username, '用户名'),
validateRequired(password, '密码'),
validateUsername(username),
validatePassword(password)
]);
if (!validation.valid) {
throw new ValidationError('数据验证失败', validation.errors);
}
// 验证邮箱格式(如果提供了)
if (email && !validateEmail(email).valid) {
throw new ValidationError('邮箱格式不正确');
}
// 检查用户名是否已存在
const usernameExists = await User.isUsernameExists(username);
if (usernameExists) {
throw new BusinessError('用户名已被使用', 400);
}
// 检查邮箱是否已存在(如果提供了)
if (email) {
const emailExists = await User.isEmailExists(email);
if (emailExists) {
throw new BusinessError('邮箱已被使用', 400);
}
}
// 加密密码
const hashedPassword = await hashPassword(password);
// 创建用户
const newUser = await User.create({
username,
password: hashedPassword,
real_name,
phone,
email,
role: role || 'customer' // 默认角色为顾客
});
// 生成token
const token = generateToken({
id: newUser.id,
username: newUser.username,
role: newUser.role
});
res.status(201).json(success({
user: newUser,
token
}, '注册成功'));
} catch (err) {
next(err);
}
};
/**
* 用户登录
* POST /api/auth/login
*/
const login = async (req, res, next) => {
try {
const { username, password } = req.body;
// 数据验证
const validation = validateBatch([
validateRequired(username, '用户名'),
validateRequired(password, '密码')
]);
if (!validation.valid) {
throw new ValidationError('数据验证失败', validation.errors);
}
// 查找用户
const user = await User.findByUsername(username);
if (!user) {
throw new BusinessError('用户名或密码错误', 401);
}
// 检查用户状态
if (user.status === 0) {
throw new BusinessError('账号已被禁用,请联系管理员', 403);
}
// 验证密码
const isPasswordValid = await comparePassword(password, user.password);
if (!isPasswordValid) {
throw new BusinessError('用户名或密码错误', 401);
}
// 生成token
const token = generateToken({
id: user.id,
username: user.username,
role: user.role
});
// 返回用户信息(不包含密码)
const userWithoutPassword = await User.findByIdWithoutPassword(user.id);
res.json(success({
user: userWithoutPassword,
token
}, '登录成功'));
} catch (err) {
next(err);
}
};
/**
* 获取当前登录用户信息
* GET /api/auth/profile
* 需要认证
*/
const getProfile = async (req, res, next) => {
try {
// req.user 由 authenticate 中间件设置
const user = await User.findByIdWithoutPassword(req.user.id);
if (!user) {
throw new BusinessError('用户不存在', 404);
}
res.json(success(user, '获取用户信息成功'));
} catch (err) {
next(err);
}
};
/**
* 更新当前用户信息
* PUT /api/auth/profile
* 需要认证
*/
const updateProfile = async (req, res, next) => {
try {
const { real_name, phone, email, avatar } = req.body;
// 验证邮箱格式(如果提供了)
if (email && !validateEmail(email).valid) {
throw new ValidationError('邮箱格式不正确');
}
// 检查邮箱是否被其他用户使用
if (email) {
const emailExists = await User.isEmailExists(email, req.user.id);
if (emailExists) {
throw new BusinessError('邮箱已被其他用户使用', 400);
}
}
// 更新用户信息
const updatedUser = await User.update(req.user.id, {
real_name,
phone,
email,
avatar
});
res.json(success(updatedUser, '更新成功'));
} catch (err) {
next(err);
}
};
/**
* 修改密码
* PUT /api/auth/password
* 需要认证
*/
const changePassword = async (req, res, next) => {
try {
const { old_password, new_password } = req.body;
// 数据验证
const validation = validateBatch([
validateRequired(old_password, '旧密码'),
validateRequired(new_password, '新密码'),
validatePassword(new_password)
]);
if (!validation.valid) {
throw new ValidationError('数据验证失败', validation.errors);
}
// 检查新旧密码是否相同
if (old_password === new_password) {
throw new BusinessError('新密码不能与旧密码相同', 400);
}
// 获取用户信息
const user = await User.findById(req.user.id);
if (!user) {
throw new BusinessError('用户不存在', 404);
}
// 验证旧密码
const isPasswordValid = await comparePassword(old_password, user.password);
if (!isPasswordValid) {
throw new BusinessError('旧密码错误', 400);
}
// 加密新密码
const hashedPassword = await hashPassword(new_password);
// 更新密码
await User.updatePassword(req.user.id, hashedPassword);
res.json(success(null, '密码修改成功,请重新登录'));
} catch (err) {
next(err);
}
};
/**
* 获取用户列表(仅管理员)
* GET /api/auth/users
* 需要认证 + 管理员权限
*/
const getUserList = async (req, res, next) => {
try {
const { page = 1, pageSize = 10, role, status } = req.query;
const result = await User.findAll({
page: parseInt(page),
pageSize: parseInt(pageSize),
role,
status: status !== undefined ? parseInt(status) : undefined
});
res.json(success({
list: result.list,
pagination: {
total: result.total,
page: result.page,
pageSize: result.pageSize,
totalPages: Math.ceil(result.total / result.pageSize)
}
}, '获取用户列表成功'));
} catch (err) {
next(err);
}
};
/**
* 更新用户状态(仅管理员)
* PUT /api/auth/users/:id/status
* 需要认证 + 管理员权限
*/
const updateUserStatus = async (req, res, next) => {
try {
const { id } = req.params;
const { status } = req.body;
// 验证status值
if (status !== 0 && status !== 1) {
throw new ValidationError('状态值必须为0或1');
}
// 不能禁用自己
if (parseInt(id) === req.user.id) {
throw new BusinessError('不能禁用自己的账号', 400);
}
// 检查用户是否存在
const user = await User.findById(id);
if (!user) {
throw new BusinessError('用户不存在', 404);
}
// 更新状态
await User.updateStatus(id, status);
res.json(success(null, status === 1 ? '用户已启用' : '用户已禁用'));
} catch (err) {
next(err);
}
};
/**
* 删除用户(仅管理员)
* DELETE /api/auth/users/:id
* 需要认证 + 管理员权限
*/
const deleteUser = async (req, res, next) => {
try {
const { id } = req.params;
// 不能删除自己
if (parseInt(id) === req.user.id) {
throw new BusinessError('不能删除自己的账号', 400);
}
// 检查用户是否存在
const user = await User.findById(id);
if (!user) {
throw new BusinessError('用户不存在', 404);
}
// 删除用户
await User.delete(id);
res.json(success(null, '用户已删除'));
} catch (err) {
next(err);
}
};
// 导出所有控制器函数
module.exports = {
register,
login,
getProfile,
updateProfile,
changePassword,
getUserList,
updateUserStatus,
deleteUser
};