Feat: change user email freezes limit (#22912)

Co-authored-by: Yansong Zhang <916125788@qq.com>
This commit is contained in:
KVOJJJin 2025-07-25 08:48:23 +08:00 committed by GitHub
parent 206bc4b36d
commit d6b980a2dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 23 additions and 4 deletions

View File

@ -511,6 +511,8 @@ class CheckEmailUnique(Resource):
parser = reqparse.RequestParser()
parser.add_argument("email", type=email, required=True, location="json")
args = parser.parse_args()
if AccountService.is_account_in_freeze(args["email"]):
raise AccountInFreezeError()
if not AccountService.check_email_unique(args["email"]):
raise EmailAlreadyInUseError()
return {"result": "success"}

View File

@ -15,6 +15,8 @@ import {
verifyEmail,
} from '@/service/common'
import { noop } from 'lodash-es'
import { asyncRunSafe } from '@/utils'
import type { ResponseError } from '@/service/fetch'
type Props = {
show: boolean
@ -39,6 +41,7 @@ const EmailChangeModal = ({ onClose, email, show }: Props) => {
const [time, setTime] = useState<number>(0)
const [stepToken, setStepToken] = useState<string>('')
const [newEmailExited, setNewEmailExited] = useState<boolean>(false)
const [unAvailableEmail, setUnAvailableEmail] = useState<boolean>(false)
const [isCheckingEmail, setIsCheckingEmail] = useState<boolean>(false)
const startCount = () => {
@ -124,9 +127,17 @@ const EmailChangeModal = ({ onClose, email, show }: Props) => {
email,
})
setNewEmailExited(false)
setUnAvailableEmail(false)
}
catch {
setNewEmailExited(true)
catch (e: any) {
if (e.status === 400) {
const [, errRespData] = await asyncRunSafe<ResponseError>(e.json())
const { code } = errRespData || {}
if (code === 'email_already_in_use')
setNewEmailExited(true)
if (code === 'account_in_freeze')
setUnAvailableEmail(true)
}
}
finally {
setIsCheckingEmail(false)
@ -291,15 +302,18 @@ const EmailChangeModal = ({ onClose, email, show }: Props) => {
placeholder={t('common.account.changeEmail.emailPlaceholder')}
value={mail}
onChange={e => handleNewEmailValueChange(e.target.value)}
destructive={newEmailExited}
destructive={newEmailExited || unAvailableEmail}
/>
{newEmailExited && (
<div className='body-xs-regular mt-1 py-0.5 text-text-destructive'>{t('common.account.changeEmail.existingEmail')}</div>
)}
{unAvailableEmail && (
<div className='body-xs-regular mt-1 py-0.5 text-text-destructive'>{t('common.account.changeEmail.unAvailableEmail')}</div>
)}
</div>
<div className='mt-3 space-y-2'>
<Button
disabled={!mail || newEmailExited || isCheckingEmail || !isValidEmail(mail)}
disabled={!mail || newEmailExited || unAvailableEmail || isCheckingEmail || !isValidEmail(mail)}
className='!w-full'
variant='primary'
onClick={sendCodeToNewEmail}

View File

@ -248,6 +248,7 @@ const translation = {
emailLabel: 'New email',
emailPlaceholder: 'Enter a new email',
existingEmail: 'A user with this email already exists.',
unAvailableEmail: 'This email is temporarily unavailable.',
sendVerifyCode: 'Send verification code',
continue: 'Continue',
changeTo: 'Change to {{email}}',

View File

@ -249,6 +249,7 @@ const translation = {
emailLabel: '新しいメール',
emailPlaceholder: '新しいメールを入力してください',
existingEmail: 'このメールアドレスのユーザーは既に存在します',
unAvailableEmail: 'このメールアドレスは現在使用できません。',
sendVerifyCode: '確認コードを送信',
continue: '続行',
changeTo: '{{email}} に変更',

View File

@ -248,6 +248,7 @@ const translation = {
emailLabel: '新邮箱',
emailPlaceholder: '输入新邮箱',
existingEmail: '该邮箱已存在',
unAvailableEmail: '该邮箱暂时无法使用。',
sendVerifyCode: '发送验证码',
continue: '继续',
changeTo: '更改为 {{email}}',