refactor(user): 重构用户模块代码

- 将 userController、userModel、userRepository 和 userService 文件中的代码进行重新组织和优化
- 使用 import 语句替代 require 引入模块
- 将函数定义从 es5 改为 es6 语法
- 优化了部分函数的实现,提高了代码可读性和维护性
This commit is contained in:
LingandRX 2025-01-05 00:13:10 +08:00
parent 4edd3c2a26
commit e6adea5f52
5 changed files with 230 additions and 214 deletions

View File

@ -6,121 +6,125 @@ import messages from '../config/messages'
import { HTTP_STATUS } from '../common/constant/httpStatus' import { HTTP_STATUS } from '../common/constant/httpStatus'
import { SearchQuery } from '../models/search' import { SearchQuery } from '../models/search'
export async function getAllUsers(res) { export default UserController = {
try { async getAllUsers(res) {
const users = await userService.getUserList()
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, 'success', users)
} catch (err) {
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
}
}
export async function findUserList(req, res) {
try {
const { page, size, sort } = req.query
const search = new SearchQuery({ page: page, size: size, sort: sort })
const result = await userService.getUserList(search)
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, 'success', result)
} catch (err) {
console.log(err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
}
}
export const createUser = [
body('account').isLength({ min: 3 }).withMessage('Account must be at least 3 characters long'),
body('account').isEmpty().withMessage('Account is required'),
body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters long'),
body('password').isEmpty().withMessage('Password is required'),
async (req, res, next) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
return FetchResult.formatResult(
res,
HTTP_STATUS.BAD_REQUEST,
errors
.array()
.map((err) => err.msg)
.join(', ')
)
}
next()
},
async (req, res) => {
try { try {
const user = req.body const users = await userService.getUserList()
await userService.createUser(user) return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, 'success', users)
return FetchResult.formatResult(res, HTTP_STATUS.CREATED, messages.user.created)
} catch (err) { } catch (err) {
logger('Error creating user: ', err)
if (err.message === messages.user.alreadyExists) {
return FetchResult.formatResult(res, HTTP_STATUS.CONFLICT, messages.user.alreadyExists)
}
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error') return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
} }
}
]
export const login = [
body('account').notEmpty().withMessage('Account is required'),
body('password').notEmpty().withMessage('Password is required'),
async (req, res, next) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
console.log(errors)
return FetchResult.formatResult(
res,
400,
errors
.array()
.map((err) => err.msg)
.join(', ')
)
}
next()
}, },
async (req, res) => {
try {
const { account, password } = req.body
req.session.user = await userService.login(account, password)
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, messages.user.login)
} catch (err) {
if (err.message === messages.user.not_found) {
return FetchResult.formatResult(res, HTTP_STATUS.NOT_FOUND, messages.user.accountPasswordNotMatch)
}
logger('Error logging in: ', err) async findUserList(req, res) {
try {
const { page, size, sort } = req.query
const search = new SearchQuery({ page: page, size: size, sort: sort })
const result = await userService.getUserList(search)
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, 'success', result)
} catch (err) {
console.log(err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error') return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
} }
} },
]
export async function logout(req, res) { createUser: [
try { body('account').isLength({ min: 3 }).withMessage('Account must be at least 3 characters long'),
req.session.destroy() body('account').isEmpty().withMessage('Account is required'),
return FetchResult.formatResult(res, HTTP_STATUS.OK, messages.user.logout) body('password').isLength({ min: 6 }).withMessage('Password must be at least 6 characters long'),
} catch (err) { body('password').isEmpty().withMessage('Password is required'),
logger('Error logging out: ', err) async (req, res, next) => {
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error') const errors = validationResult(req)
} if (!errors.isEmpty()) {
} return FetchResult.formatResult(
res,
HTTP_STATUS.BAD_REQUEST,
errors
.array()
.map((err) => err.msg)
.join(', ')
)
}
export async function getUserExists(req, res) { next()
try { },
const { account } = req.query async (req, res) => {
try {
const exist = await userService.getUserExists(account) const user = req.body
await userService.createUser(user)
if (!exist) { return FetchResult.formatResult(res, HTTP_STATUS.CREATED, messages.user.created)
return FetchResult.formatResult(res, HTTP_STATUS.NOT_FOUND, messages.user.not_found) } catch (err) {
logger('Error creating user: ', err)
if (err.message === messages.user.alreadyExists) {
return FetchResult.formatResult(res, HTTP_STATUS.CONFLICT, messages.user.alreadyExists)
}
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
}
}
],
login: [
body('account').notEmpty().withMessage('Account is required'),
body('password').notEmpty().withMessage('Password is required'),
async (req, res, next) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
console.log(errors)
return FetchResult.formatResult(
res,
400,
errors
.array()
.map((err) => err.msg)
.join(', ')
)
}
next()
},
async (req, res) => {
try {
const { account, password } = req.body
req.session.user = await userService.login(account, password)
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, messages.user.login)
} catch (err) {
if (err.message === messages.user.not_found) {
return FetchResult.formatResult(res, HTTP_STATUS.NOT_FOUND, messages.user.accountPasswordNotMatch)
}
logger('Error logging in: ', err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
}
}
],
logout: [
async (req, res) => {
try {
req.session.destroy()
return FetchResult.formatResult(res, HTTP_STATUS.OK, messages.user.logout)
} catch (err) {
logger('Error logging out: ', err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
}
}
],
async getUserExists(req, res) {
try {
const { account } = req.query
const exist = await userService.getUserExists(account)
if (!exist) {
return FetchResult.formatResult(res, HTTP_STATUS.NOT_FOUND, messages.user.not_found)
}
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, messages.user.exists)
} catch (err) {
logger('Error checking user existence: ', err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
} }
return FetchResult.formatResult(res, HTTP_STATUS.ACCEPTED, messages.user.exists)
} catch (err) {
logger('Error checking user existence: ', err)
return FetchResult.formatResult(res, HTTP_STATUS.INTERNAL_SERVER_ERROR, 'Internal server error')
} }
} }

View File

@ -1,6 +1,6 @@
const mongoose = require('mongoose') import { Schema as _Schema, model } from 'mongoose'
const { hashPassword } = require('../utils/hashUtils') import { hashPassword } from '../utils/hashUtils'
const Schema = mongoose.Schema const Schema = _Schema
const UserSchema = new Schema({ const UserSchema = new Schema({
name: { type: String, required: true, maxlength: 100 }, name: { type: String, required: true, maxlength: 100 },
@ -29,4 +29,4 @@ UserSchema.pre('save', async function (next) {
} }
}) })
module.exports = mongoose.model('User', UserSchema) export default model('User', UserSchema)

View File

@ -1,25 +1,36 @@
const UserModel = require('../models/userModel') import {
const { SearchResult } = require('../models/search') startSession,
find,
aggregate,
findById,
findOne,
exists,
create,
findByIdAndUpdate,
findByIdAndDelete,
deleteMany
} from '../models/userModel'
import { SearchResult } from '../models/search'
exports.startTransaction = async () => { export async function startTransaction() {
const session = await UserModel.startSession() const session = await startSession()
session.startTransaction() session.startTransaction()
return session return session
} }
exports.commitTransaction = async (session) => { export async function commitTransaction(session) {
return session.commitTransaction() return session.commitTransaction()
} }
exports.rollbackTransaction = async (session) => { export async function rollbackTransaction(session) {
return session.abortTransaction() return session.abortTransaction()
} }
exports.selectAllUser = async () => { export async function selectAllUser() {
return UserModel.find() return find()
} }
exports.selectUserList = async (search = {}) => { export async function selectUserList(search = {}) {
try { try {
const { size = 20, page = 1, sort, filters } = search const { size = 20, page = 1, sort, filters } = search
@ -32,7 +43,7 @@ exports.selectUserList = async (search = {}) => {
const matchFilters = filters ? { ...filters } : {} const matchFilters = filters ? { ...filters } : {}
const sortObj = sort && typeof sort === 'object' ? sort : { _id: 1 } // 默认按 _id 升序排序 const sortObj = sort && typeof sort === 'object' ? sort : { _id: 1 } // 默认按 _id 升序排序
const result = await UserModel.aggregate([ const result = await aggregate([
// 应用过滤条件确保filters存在时才传入 // 应用过滤条件确保filters存在时才传入
{ $match: matchFilters }, { $match: matchFilters },
{ {
@ -57,47 +68,47 @@ exports.selectUserList = async (search = {}) => {
} }
} }
exports.selectUserById = async (id) => { export async function selectUserById(id) {
return UserModel.findById(id) return findById(id)
} }
exports.selectUserByAccount = async (account) => { export async function selectUserByAccount(account) {
return UserModel.findOne({ account: account }) return findOne({ account: account })
} }
exports.selectUserByEmail = async (email) => { export async function selectUserByEmail(email) {
return UserModel.findOne({ email: email }) return findOne({ email: email })
} }
exports.selectUserByUsername = async (username) => { export async function selectUserByUsername(username) {
return UserModel.findOne({ username: username }) return findOne({ username: username })
} }
exports.selectUserByPhone = async (phone) => { export async function selectUserByPhone(phone) {
return UserModel.findOne({ phone: phone }) return findOne({ phone: phone })
} }
exports.selectUserByAccountExist = async (account) => { export async function selectUserByAccountExist(account) {
const exist = await UserModel.exists({ account: account }) const exist = await exists({ account: account })
return exist !== null return exist !== null
} }
exports.createUser = async (user) => { export async function createUser(user) {
return UserModel.create(user) return create(user)
} }
exports.updateUserById = async (id, user) => { export async function updateUserById(id, user) {
return UserModel.findByIdAndUpdate(id, user) return findByIdAndUpdate(id, user)
} }
exports.updateUserByLoginDate = async (id, loginDate) => { export async function updateUserByLoginDate(id, loginDate) {
return UserModel.findByIdAndUpdate(id, { last_login_date: loginDate }) return findByIdAndUpdate(id, { last_login_date: loginDate })
} }
exports.deleteUserById = async (id) => { export async function deleteUserById(id) {
return UserModel.findByIdAndDelete(id) return findByIdAndDelete(id)
} }
exports.deleteAllUser = async () => { export async function deleteAllUser() {
return UserModel.deleteMany() return deleteMany()
} }

View File

@ -1,10 +1,9 @@
// routes/userRoutes.js // routes/userRoutes.js
import express from 'express' import express from 'express'
const userController = import('../controllers/userController')
import userController from '../controllers/userController'
const router = express.Router() const router = express.Router()
router.get('/', userController.getUserExist) router.get('/', getUserExists)
export default router export default router

View File

@ -3,80 +3,82 @@ import logger from 'morgan'
import messages from '../config/messages' import messages from '../config/messages'
import { comparePassword } from '../utils/hashUtils' import { comparePassword } from '../utils/hashUtils'
/** export default userServeice = {
* 用户登录 /**
* @param {string} account - 用户账号 * 用户登录
* @param {string} password - 用户密码 * @param {string} account - 用户账号
* @returns {Promise<Object>} - 登录成功返回用户信息 * @param {string} password - 用户密码
* @throws {Error} - 如果用户不存在或密码不正确 * @returns {Promise<Object>} - 登录成功返回用户信息
*/ * @throws {Error} - 如果用户不存在或密码不正确
export async function login(account, password) { */
const user = await userMapper.selectUserByAccount(account) async login(account, password) {
const user = await userMapper.selectUserByAccount(account)
// 用户不存在 // 用户不存在
if (!user) { if (!user) {
throw new Error(messages.user.not_found) throw new Error(messages.user.not_found)
}
// 密码不匹配
const isMatch = comparePassword(password, user.password)
if (!isMatch) {
throw new Error(messages.user.passwordIncorrect)
}
// 更新用户的最后登录时间
user.lastLoginDate = new Date()
await userMapper.updateUserByLoginDate(user.id, user.lastLoginDate)
return user
}
/**
*
* @param {string} account
* @returns {Promise<boolean>}
*/
export async function getUserExists(account) {
return userMapper.selectUserByAccountExist(account)
}
// Removed the unnecessary try-catch block and simplified the function
export async function getAllUser() {
return await userMapper.selectAllUser()
}
export async function getUserList(searchQuery) {
return userMapper.selectUserList(searchQuery)
}
/**
* 创建用户
* @param {Object} user - 用户对象
* @returns {Promise<Object>} - 创建成功的用户信息
* @throws {Error} - 如果用户已存在或事务失败
*/
export async function createUser(user) {
const { account } = user
const session = await userMapper.startTransaction()
try {
// 检查用户是否已存在
const existingUser = await userMapper.selectUserByAccount(account)
if (existingUser) {
return new Error(messages.user.alreadyExists)
} }
// 创建新用户 // 密码不匹配
const result = await userMapper.createUser(user) const isMatch = comparePassword(password, user.password)
if (!isMatch) {
throw new Error(messages.user.passwordIncorrect)
}
// 提交事务 // 更新用户的最后登录时间
await userMapper.commitTransaction(session) user.lastLoginDate = new Date()
return result await userMapper.updateUserByLoginDate(user.id, user.lastLoginDate)
} catch (err) {
// 回滚事务 return user
await userMapper.rollbackTransaction(session).catch((rollbackErr) => { },
logger('Error rolling back transaction: ', rollbackErr)
}) /**
throw err // 将错误抛给调用方Controller 层) *
* @param {string} account
* @returns {Promise<boolean>}
*/
async getUserExists(account) {
return userMapper.selectUserByAccountExist(account)
},
// Removed the unnecessary try-catch block and simplified the function
async getAllUser() {
return await userMapper.selectAllUser()
},
async getUserList(searchQuery) {
return userMapper.selectUserList(searchQuery)
},
/**
* 创建用户
* @param {Object} user - 用户对象
* @returns {Promise<Object>} - 创建成功的用户信息
* @throws {Error} - 如果用户已存在或事务失败
*/
async createUser(user) {
const { account } = user
const session = await userMapper.startTransaction()
try {
// 检查用户是否已存在
const existingUser = await userMapper.selectUserByAccount(account)
if (existingUser) {
return new Error(messages.user.alreadyExists)
}
// 创建新用户
const result = await userMapper.createUser(user)
// 提交事务
await userMapper.commitTransaction(session)
return result
} catch (err) {
// 回滚事务
await userMapper.rollbackTransaction(session).catch((rollbackErr) => {
logger('Error rolling back transaction: ', rollbackErr)
})
throw err // 将错误抛给调用方Controller 层)
}
} }
} }