From ee22a661e80ba88e0dc5208121784628f7443707 Mon Sep 17 00:00:00 2001 From: Aether_254 <67494671+Aether-254@users.noreply.github.com> Date: Sat, 26 Sep 2026 19:53:16 +0800 Subject: [PATCH 1/2] fix(user): verify current pay key before update --- docs/docs.go | 6 +- docs/swagger.json | 6 +- docs/swagger.yaml | 3 +- .../components/common/settings/security.tsx | 81 +++++++++++--- frontend/contexts/user-context.tsx | 6 +- frontend/lib/services/user/index.ts | 2 +- frontend/lib/services/user/types.ts | 3 +- frontend/lib/services/user/user.service.ts | 11 +- internal/apps/user/errs.go | 4 +- internal/apps/user/pay_key_test.go | 104 ++++++++++++++++++ internal/apps/user/routers.go | 34 +++++- 11 files changed, 229 insertions(+), 31 deletions(-) create mode 100644 internal/apps/user/pay_key_test.go diff --git a/docs/docs.go b/docs/docs.go index cbb8e673..6ccbf093 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -2620,9 +2620,11 @@ const docTemplate = `{ "pay_key" ], "properties": { + "current_pay_key": { + "type": "string" + }, "pay_key": { - "type": "string", - "maxLength": 6 + "type": "string" } } }, diff --git a/docs/swagger.json b/docs/swagger.json index 003dc0fb..04f5469a 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -2611,9 +2611,11 @@ "pay_key" ], "properties": { + "current_pay_key": { + "type": "string" + }, "pay_key": { - "type": "string", - "maxLength": 6 + "type": "string" } } }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index f42a3d17..90949f96 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -516,8 +516,9 @@ definitions: type: object user.UpdatePayKeyRequest: properties: + current_pay_key: + type: string pay_key: - maxLength: 6 type: string required: - pay_key diff --git a/frontend/components/common/settings/security.tsx b/frontend/components/common/settings/security.tsx index c13f6801..c8c2ab60 100644 --- a/frontend/components/common/settings/security.tsx +++ b/frontend/components/common/settings/security.tsx @@ -11,19 +11,35 @@ import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbP import { Button } from "@/components/ui/button" import { InputOTP, InputOTPGroup, InputOTPSlot } from "@/components/ui/input-otp" import { Spinner } from "@/components/ui/spinner" +import { useUser } from "@/contexts/user-context" import { UserService } from "@/lib/services/user" export function SecurityMain() { const router = useRouter() - const [setupStep, setSetupStep] = React.useState<'password' | 'confirm'>('password') + const { user } = useUser() + const hasPayKey = user?.is_pay_key ?? true + const [setupStep, setSetupStep] = React.useState<'current' | 'password' | 'confirm'>('current') + const [currentPayKey, setCurrentPayKey] = React.useState("") const [payKey, setPayKey] = React.useState("") const [confirmPayKey, setConfirmPayKey] = React.useState("") const [isSubmitting, setIsSubmitting] = React.useState(false) + const isCurrentPayKeyValid = currentPayKey.length === 6 && /^\d{6}$/.test(currentPayKey) const isPayKeyValid = payKey.length === 6 && /^\d{6}$/.test(payKey) const isConfirmValid = confirmPayKey.length === 6 && /^\d{6}$/.test(confirmPayKey) const passwordsMatch = payKey === confirmPayKey + React.useEffect(() => { + if (user && !user.is_pay_key) { + setSetupStep('password') + } + }, [user]) + + /* 原安全密码输入 */ + const handleCurrentPayKeyChange = (value: string) => { + setCurrentPayKey(value.replaceAll(/\D/g, '')) + } + /* 安全密码输入 */ const handlePayKeyChange = (value: string) => { const numericValue = value.replaceAll(/\D/g, '') @@ -39,7 +55,13 @@ export function SecurityMain() { const handlePayKeySubmit = async (e: React.FormEvent) => { e.preventDefault() - if (setupStep === 'password') { + if (setupStep === 'current') { + if (!isCurrentPayKeyValid) { + toast.error("原安全密码必须为6位数字") + return + } + setSetupStep('password') + } else if (setupStep === 'password') { if (!isPayKeyValid) { toast.error("安全密码必须为6位数字") return @@ -60,7 +82,7 @@ export function SecurityMain() { setIsSubmitting(true) try { - await UserService.updatePayKey(payKey) + await UserService.updatePayKey(payKey, hasPayKey ? currentPayKey : undefined) toast.success("修改成功", { description: "您的安全密码已成功更新", }) @@ -71,7 +93,9 @@ export function SecurityMain() { toast.error("修改失败", { description: error instanceof Error ? error.message : "更新密码时发生错误,请稍后重试", }) - setSetupStep('password') + setSetupStep(hasPayKey ? 'current' : 'password') + setCurrentPayKey("") + setPayKey("") setConfirmPayKey("") } finally { setIsSubmitting(false) @@ -121,18 +145,38 @@ export function SecurityMain() { >
- {setupStep === 'password' - ? '请输入新的6位数字安全密码' - : '请再次输入密码进行确认'} + {setupStep === 'current' + ? '请输入当前的6位数字安全密码' + : setupStep === 'password' + ? '请输入新的6位数字安全密码' + : '请再次输入密码进行确认'}