feat(user): 重构用户控制器,添加统一的响应格式和错误处理,优化登录和创建用户功能
This commit is contained in:
parent
ee5ec21aa3
commit
6183aa4da5
8
app.js
8
app.js
@ -37,7 +37,13 @@ app.use(
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
app.use(cors())
|
const corsOptions = {
|
||||||
|
origin: 'http://localhost:5173', // 指定允许的源
|
||||||
|
credentials: true, // 允许发送凭据(如 cookies)
|
||||||
|
optionsSuccessStatus: 200 // 一些旧的浏览器(IE11, various SmartTVs)需要这个
|
||||||
|
};
|
||||||
|
|
||||||
|
app.use(cors(corsOptions))
|
||||||
|
|
||||||
async function startServer() {
|
async function startServer() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
75
common/constant/httpStatus.js
Normal file
75
common/constant/httpStatus.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* HTTP 状态码常量
|
||||||
|
*/
|
||||||
|
export const HTTP_STATUS = {
|
||||||
|
// 信息响应 (100–199)
|
||||||
|
CONTINUE: 100,
|
||||||
|
SWITCHING_PROTOCOLS: 101,
|
||||||
|
PROCESSING: 102,
|
||||||
|
|
||||||
|
// 成功响应 (200–299)
|
||||||
|
OK: 200, // 请求成功
|
||||||
|
CREATED: 201, // 请求成功并且服务器创建了新的资源
|
||||||
|
ACCEPTED: 202, // 已接受
|
||||||
|
NON_AUTHORITATIVE_INFORMATION: 203, // 非权威信息
|
||||||
|
NO_CONTENT: 204, // 没有内容
|
||||||
|
RESET_CONTENT: 205, // 重置内容
|
||||||
|
PARTIAL_CONTENT: 206, // 部分内容
|
||||||
|
MULTI_STATUS: 207, // 多状态
|
||||||
|
ALREADY_REPORTED: 208, // 已报告
|
||||||
|
IM_USED: 226, // 我被使用
|
||||||
|
|
||||||
|
// 重定向消息 (300–399)
|
||||||
|
MULTIPLE_CHOICES: 300, // 多种选择
|
||||||
|
MOVED_PERMANENTLY: 301, // 永久移动
|
||||||
|
FOUND: 302, // 查找
|
||||||
|
SEE_OTHER: 303, // 查看其他位置
|
||||||
|
NOT_MODIFIED: 304, // 未修改
|
||||||
|
USE_PROXY: 305, // 使用代理
|
||||||
|
TEMPORARY_REDIRECT: 307, // 临时重定向
|
||||||
|
PERMANENT_REDIRECT: 308, // 永久重定向
|
||||||
|
|
||||||
|
// 客户端错误响应 (400–499)
|
||||||
|
BAD_REQUEST: 400, // 错误请求
|
||||||
|
UNAUTHORIZED: 401, // 未授权
|
||||||
|
PAYMENT_REQUIRED: 402, // 需要付款
|
||||||
|
FORBIDDEN: 403, // 禁止
|
||||||
|
NOT_FOUND: 404, // 未找到
|
||||||
|
METHOD_NOT_ALLOWED: 405, // 方法禁用
|
||||||
|
NOT_ACCEPTABLE: 406, // 请求不接受
|
||||||
|
PROXY_AUTHENTICATION_REQUIRED: 407, // 需要代理认证
|
||||||
|
REQUEST_TIMEOUT: 408, // 请求超时
|
||||||
|
CONFLICT: 409, // 冲突
|
||||||
|
GONE: 410, // 已删除
|
||||||
|
LENGTH_REQUIRED: 411, // 需要长度
|
||||||
|
PRECONDITION_FAILED: 412, // 前提条件失败
|
||||||
|
PAYLOAD_TOO_LARGE: 413, // 负载过大
|
||||||
|
URI_TOO_LONG: 414, // URI 过长
|
||||||
|
UNSUPPORTED_MEDIA_TYPE: 415, // 不支持的媒体类型
|
||||||
|
RANGE_NOT_SATISFIABLE: 416, // 请求范围不符合要求
|
||||||
|
EXPECTATION_FAILED: 417, // 期望失败
|
||||||
|
IM_A_TEAPOT: 418, // 我是一个茶壶
|
||||||
|
MISDIRECTED_REQUEST: 421, // 请求错位
|
||||||
|
UNPROCESSABLE_ENTITY: 422, // 无法处理的实体
|
||||||
|
LOCKED: 423, // 锁定
|
||||||
|
FAILED_DEPENDENCY: 424, // 失败依赖
|
||||||
|
TOO_EARLY: 425, // 太早
|
||||||
|
UPGRADE_REQUIRED: 426, // 升级所需
|
||||||
|
PRECONDITION_REQUIRED: 428, // 必须的前提条件
|
||||||
|
TOO_MANY_REQUESTS: 429, // 请求过多
|
||||||
|
REQUEST_HEADER_FIELDS_TOO_LARGE: 431, // 请求头字段太大
|
||||||
|
UNAVAILABLE_FOR_LEGAL_REASONS: 451, // 因法律原因不可用
|
||||||
|
|
||||||
|
// 服务器错误响应 (500–599)
|
||||||
|
INTERNAL_SERVER_ERROR: 500, // 内部服务器错误
|
||||||
|
NOT_IMPLEMENTED: 501, // 尚未实施
|
||||||
|
BAD_GATEWAY: 502, // 错误网关
|
||||||
|
SERVICE_UNAVAILABLE: 503, // 服务不可用
|
||||||
|
GATEWAY_TIMEOUT: 504, // 网关超时
|
||||||
|
HTTP_VERSION_NOT_SUPPORTED: 505, // HTTP 版本不受支持
|
||||||
|
VARIANT_ALSO_NEGOTIATES: 506, // 变体也协商
|
||||||
|
INSUFFICIENT_STORAGE: 507, // 存储不足
|
||||||
|
LOOP_DETECTED: 508, // 检测到循环
|
||||||
|
NOT_EXTENDED: 510, // 未扩展
|
||||||
|
NETWORK_AUTHENTICATION_REQUIRED: 511 // 需要网络认证
|
||||||
|
}
|
||||||
19
common/web/fetchResult.js
Normal file
19
common/web/fetchResult.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
class FetchResult {
|
||||||
|
constructor(code, msg, data = null) {
|
||||||
|
if (typeof code !== 'number') {
|
||||||
|
throw new Error('Code must be a number')
|
||||||
|
}
|
||||||
|
if (typeof msg !== 'string') {
|
||||||
|
throw new Error('Msg must be a string')
|
||||||
|
}
|
||||||
|
this.code = code
|
||||||
|
this.msg = msg
|
||||||
|
this.data = data !== undefined && data !== null ? data : null
|
||||||
|
}
|
||||||
|
|
||||||
|
static formatResult(res, code, msg, data = null) {
|
||||||
|
return res.status(code).json(new FetchResult(code, msg, data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = FetchResult
|
||||||
@ -2,6 +2,7 @@ module.exports = {
|
|||||||
user: {
|
user: {
|
||||||
not_found: 'User not found',
|
not_found: 'User not found',
|
||||||
already_exists: 'User already exists',
|
already_exists: 'User already exists',
|
||||||
|
account_password_not_match: 'Account and password not match',
|
||||||
account_not_match: 'Account not match',
|
account_not_match: 'Account not match',
|
||||||
password_not_match: 'Password not match',
|
password_not_match: 'Password not match',
|
||||||
password_incorrect: 'Password incorrect'
|
password_incorrect: 'Password incorrect'
|
||||||
|
|||||||
@ -1,28 +1,34 @@
|
|||||||
const { body, validationResult } = require('express-validator')
|
const { body, validationResult } = require('express-validator')
|
||||||
const userService = require('../services/userService')
|
const userService = require('../services/userService')
|
||||||
|
const FetchResult = require('../common/web/fetchResult')
|
||||||
const errorMessages = require('../config/errorMessages')
|
const errorMessages = require('../config/errorMessages')
|
||||||
const successMessages = require('../config/successMessages')
|
const successMessages = require('../config/successMessages')
|
||||||
|
|
||||||
exports.getAllUsers = async (req, res) => {
|
exports.getAllUsers = async (res) => {
|
||||||
try {
|
try {
|
||||||
const users = await userService.user_list()
|
const users = await userService.user_list()
|
||||||
res.json(users)
|
return FetchResult.formatResult(res, 200, 'success', users)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(500).json({ error: err.message })
|
return FetchResult.formatResult(res, 500, 'Internal server error')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.createUser = [
|
exports.createUser = [
|
||||||
body('account').isLength({ min: 3 }).withMessage('Account must be at least 3 characters long'),
|
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').isLength({ min: 6 }).withMessage('Password must be at least 6 characters long'),
|
||||||
|
body('password').isEmpty().withMessage('Password is required'),
|
||||||
async (req, res, next) => {
|
async (req, res, next) => {
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req)
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
const formattedErrors = errors.array().map((err) => ({
|
return FetchResult.formatResult(
|
||||||
field: err.path, // 错误字段名
|
res,
|
||||||
message: err.msg // 错误提示消息
|
400,
|
||||||
}))
|
errors
|
||||||
return res.status(400).json({ errors: formattedErrors })
|
.array()
|
||||||
|
.map((err) => err.msg)
|
||||||
|
.join(', ')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
next()
|
||||||
@ -31,35 +37,32 @@ exports.createUser = [
|
|||||||
try {
|
try {
|
||||||
const user = req.body
|
const user = req.body
|
||||||
await userService.create_user(user)
|
await userService.create_user(user)
|
||||||
res.status(201).json({ message: successMessages.user.created })
|
return FetchResult.formatResult(res, 201, successMessages.user.created)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.message === errorMessages.user.already_exists) {
|
|
||||||
return res.status(400).json({ error: err.message })
|
|
||||||
}
|
|
||||||
logger('Error creating user: ', err)
|
logger('Error creating user: ', err)
|
||||||
return res.status(500).json({ error: 'Internal server error' })
|
if (err.message === errorMessages.user.already_exists) {
|
||||||
|
return FetchResult.formatResult(res, 400, errorMessages.user.already_exists)
|
||||||
|
}
|
||||||
|
return FetchResult.formatResult(res, 500, 'Internal server error')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
exports.login = [
|
exports.login = [
|
||||||
|
body('account').notEmpty().withMessage('Account is required'),
|
||||||
|
body('password').notEmpty().withMessage('Password is required'),
|
||||||
async (req, res, next) => {
|
async (req, res, next) => {
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req)
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
const formattedErrors = errors.array().map((err) => ({
|
console.log(errors)
|
||||||
field: err.path, // 错误字段名
|
return FetchResult.formatResult(
|
||||||
message: err.msg // 错误提示消息
|
res,
|
||||||
}))
|
400,
|
||||||
return res.status(400).json({ errors: formattedErrors })
|
errors
|
||||||
}
|
.array()
|
||||||
|
.map((err) => err.msg)
|
||||||
const { account, password } = req.body
|
.join(', ')
|
||||||
|
)
|
||||||
if (!account) {
|
|
||||||
return res.status(400).json({ error: errorMessages.user.account_not_match })
|
|
||||||
}
|
|
||||||
if (!password) {
|
|
||||||
return res.status(400).json({ error: errorMessages.user.password_not_match })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next()
|
next()
|
||||||
@ -67,21 +70,15 @@ exports.login = [
|
|||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { account, password } = req.body
|
const { account, password } = req.body
|
||||||
if (account === 'admin' && password === 'admin') {
|
|
||||||
req.session.user = { account }
|
|
||||||
return res.status(200).json({ message: successMessages.user.login })
|
|
||||||
}
|
|
||||||
const user = await userService.login(account, password)
|
|
||||||
|
|
||||||
|
const user = await userService.login(account, password)
|
||||||
req.session.user = user
|
req.session.user = user
|
||||||
res.status(200).json({ message: successMessages.user.login })
|
return FetchResult.formatResult(res, 200, successMessages.user.login)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.message === errorMessages.user.not_found) {
|
if (err.message === errorMessages.user.not_found) {
|
||||||
return res.status(404).json({ error: err.message })
|
return FetchResult.formatResult(res, 401, errorMessages.user.account_password_not_match)
|
||||||
}
|
}
|
||||||
console.log(err)
|
return FetchResult.formatResult(res, 500, 'Internal server error')
|
||||||
|
|
||||||
return res.status(500).json({ error: 'Internal server error' })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -93,11 +90,12 @@ exports.getUserExist = async (req, res) => {
|
|||||||
const { account } = req.query
|
const { account } = req.query
|
||||||
|
|
||||||
const exist = await userService.get_user_exist(account)
|
const exist = await userService.get_user_exist(account)
|
||||||
|
|
||||||
if (!exist) {
|
if (!exist) {
|
||||||
return res.status(404).json({ message: errorMessages.user.not_found }) // 用户未找到,使用 404 错误码
|
return FetchResult.formatResult(res, 404, errorMessages.user.not_found)
|
||||||
}
|
}
|
||||||
return res.status(200).json({ message: successMessages.user.exist })
|
return FetchResult.formatResult(res, 200, successMessages.user.exist)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(500).json({ error: err.message })
|
return FetchResult.formatResult(res, 500, 'Internal server error')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,20 +4,9 @@ const userController = require('../controllers/userController')
|
|||||||
|
|
||||||
|
|
||||||
router.get('/', function (req, res, next) {
|
router.get('/', function (req, res, next) {
|
||||||
res.send('respond with a resource')
|
// res.send('respond with a resource')
|
||||||
})
|
})
|
||||||
|
|
||||||
// router.post('/login', function (req, res, next) {
|
|
||||||
// const { account, password } = req.body
|
|
||||||
// console.log(account, password)
|
|
||||||
// if (account === 'admin' && password === 'admin') {
|
|
||||||
// req.session.user = { account }
|
|
||||||
// res.json({ account })
|
|
||||||
// } else {
|
|
||||||
// res.status(401).json({ error: 'Unauthorized' })
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
router.post('/login', userController.login)
|
router.post('/login', userController.login)
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user