feat(auth): 密码重置邮件队列化与限流优化
- 邮件发送改为异步队列处理,避免并发导致发送失败 - 新增 Email 维度限流(30秒冷却期),防止邮件轰炸 - Token 验证使用常量时间比较,防止时序攻击 - 重构代码消除冗余,提取公共验证逻辑
This commit is contained in:
@@ -13,6 +13,7 @@ export interface SystemSettings {
|
||||
registration_enabled: boolean
|
||||
email_verify_enabled: boolean
|
||||
promo_code_enabled: boolean
|
||||
password_reset_enabled: boolean
|
||||
// Default settings
|
||||
default_balance: number
|
||||
default_concurrency: number
|
||||
@@ -66,6 +67,7 @@ export interface UpdateSettingsRequest {
|
||||
registration_enabled?: boolean
|
||||
email_verify_enabled?: boolean
|
||||
promo_code_enabled?: boolean
|
||||
password_reset_enabled?: boolean
|
||||
default_balance?: number
|
||||
default_concurrency?: number
|
||||
site_name?: string
|
||||
|
||||
@@ -133,6 +133,57 @@ export async function validatePromoCode(code: string): Promise<ValidatePromoCode
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Forgot password request
|
||||
*/
|
||||
export interface ForgotPasswordRequest {
|
||||
email: string
|
||||
turnstile_token?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Forgot password response
|
||||
*/
|
||||
export interface ForgotPasswordResponse {
|
||||
message: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Request password reset link
|
||||
* @param request - Email and optional Turnstile token
|
||||
* @returns Response with message
|
||||
*/
|
||||
export async function forgotPassword(request: ForgotPasswordRequest): Promise<ForgotPasswordResponse> {
|
||||
const { data } = await apiClient.post<ForgotPasswordResponse>('/auth/forgot-password', request)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset password request
|
||||
*/
|
||||
export interface ResetPasswordRequest {
|
||||
email: string
|
||||
token: string
|
||||
new_password: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset password response
|
||||
*/
|
||||
export interface ResetPasswordResponse {
|
||||
message: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset password with token
|
||||
* @param request - Email, token, and new password
|
||||
* @returns Response with message
|
||||
*/
|
||||
export async function resetPassword(request: ResetPasswordRequest): Promise<ResetPasswordResponse> {
|
||||
const { data } = await apiClient.post<ResetPasswordResponse>('/auth/reset-password', request)
|
||||
return data
|
||||
}
|
||||
|
||||
export const authAPI = {
|
||||
login,
|
||||
register,
|
||||
@@ -144,7 +195,9 @@ export const authAPI = {
|
||||
clearAuthToken,
|
||||
getPublicSettings,
|
||||
sendVerifyCode,
|
||||
validatePromoCode
|
||||
validatePromoCode,
|
||||
forgotPassword,
|
||||
resetPassword
|
||||
}
|
||||
|
||||
export default authAPI
|
||||
|
||||
Reference in New Issue
Block a user