feat: add endpoint to update payer with bearer token validation and input validation

This commit is contained in:
Astrian Zheng 2025-01-12 12:59:32 +11:00
parent 28e14224e7
commit cc4c5c5ad4
Signed by: Astrian
SSH Key Fingerprint: SHA256:rVnhx3DAKjujCwWE13aDl7uV6+9U1MvydLkNRXJrBiA
3 changed files with 81 additions and 0 deletions

View File

@ -101,6 +101,48 @@ app.use(route.get('/payer', async (ctx) => {
ctx.body = payers
}))
app.use(route.put('/payer/:id', async (ctx, id) => {
// 请求头验证 bearer token
const bearerToken = ctx.request.headers['authorization']?.split(' ')
if (!bearerToken) throw new HttpError(ErrorDescEnum.unauthorized, 401)
if (bearerToken[0] !== 'Bearer') throw new HttpError(ErrorDescEnum.unauthorized, 401)
if (!bearerToken[1]) throw new HttpError(ErrorDescEnum.unauthorized, 401)
await func.verifyBearerToken(bearerToken[1])
// 验证 id 必须是数字
if (isNaN(parseInt(id))) throw new HttpError(ErrorDescEnum.invalid_field_format, 400, ['id'])
// 验证必填字段
// 字段缺失时
if (!ctx.request.body) throw new HttpError(ErrorDescEnum.required_fields_missing, 400, ['name', 'address', 'email'])
// 有字段,但为空时
const { name, address, email, abn } = ctx.request.body
let emptyFields = []
if (!name) emptyFields.push('name')
if (!address) emptyFields.push('address')
if (!email) emptyFields.push('email')
if (emptyFields.length > 0) throw new HttpError(ErrorDescEnum.required_fields_missing, 400, emptyFields)
// 验证地址格式,格式应为 string[],最多两行
if (!Array.isArray(address) || address.length > 2 || address.length <= 0) throw new HttpError(ErrorDescEnum.invalid_field_format, 400, ['address'])
// 名字应为字符串
if (typeof name !== 'string') throw new HttpError(ErrorDescEnum.invalid_field_format, 400, ['name'])
// 验证邮箱格式
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
if (!emailRegex.test(email)) throw new HttpError(ErrorDescEnum.invalid_field_format, 400, ['email'])
// 验证 ABN 格式
const abnRegex = /^\d{11}$/
if (abn && !abnRegex.test(abn)) throw new HttpError(ErrorDescEnum.invalid_field_format, 400, ['abn'])
// 更新付款人
await func.updatePayer(ctx.prisma, id, name, address, email, abn)
ctx.status = 204
}))
app.use(route.post('/invoice', async (ctx) => {
// 请求头验证 bearer token
const bearerToken = ctx.request.headers['authorization']?.split(' ')

View File

@ -4,6 +4,7 @@ import verifyBearerToken from "./verifyBearerToken"
import getSpecificInvoice from "./getSpecificInvoice"
import getInvoices from "./getInvoices"
import getPayers from "./getPayers"
import updatePayer from "./updatePayer"
export default {
createPayer,
@ -12,4 +13,5 @@ export default {
getSpecificInvoice,
getInvoices,
getPayers,
updatePayer
}

View File

@ -0,0 +1,37 @@
import { PrismaClient } from '@prisma/client'
import { ErrorDescEnum, HttpError } from '../classes/HttpError'
export default async function updatePayer(prisma: PrismaClient, id: number, name: string, address: string[], email: string, abn?: string) {
// 验证 ABN 是否已存在
const existingPayer = await prisma.payer.findFirst({
where: {
payer_abn: abn
}
})
if (existingPayer && existingPayer.payer_id !== id) {
// 验证 abn 是否已经是当前付款人的 abn
if (existingPayer.payer_id !== id) throw new HttpError(ErrorDescEnum.item_exists, 400, ['abn'])
}
// 验证付款人是否存在
const payerExists = await prisma.payer.findFirst({
where: {
payer_id: id
}
})
if (!payerExists) throw new HttpError(ErrorDescEnum.item_not_found, 404, ['payer'])
// 更新付款人
const payer = await prisma.payer.update({
where: {
payer_id: id
},
data: {
payer_name: name,
payer_address: address.join('\n'),
payer_email: email,
payer_abn: abn
}
})
return payer
}