/** * 认证控制器 * * 功能:处理用户注册、登录、获取信息等认证相关的业务逻辑 * * 说明: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 };