fix(frontend): restore pending auth session flow

This commit is contained in:
IanShaw027
2026-04-21 00:05:44 +08:00
parent 4f6966d7b3
commit 85fc54b205
6 changed files with 556 additions and 24 deletions

View File

@@ -176,7 +176,8 @@ import { AuthLayout } from '@/components/layout'
import Icon from '@/components/icons/Icon.vue'
import TurnstileWidget from '@/components/TurnstileWidget.vue'
import { useAuthStore, useAppStore } from '@/stores'
import { getPublicSettings, sendVerifyCode } from '@/api/auth'
import { persistOAuthTokenContext, getPublicSettings, sendVerifyCode } from '@/api/auth'
import { apiClient } from '@/api/client'
import { buildAuthErrorMessage } from '@/utils/authError'
import {
isRegistrationEmailSuffixAllowed,
@@ -202,11 +203,33 @@ const countdown = ref<number>(0)
let countdownTimer: ReturnType<typeof setInterval> | null = null
// Registration data from sessionStorage
type PendingAuthTokenField = 'pending_auth_token' | 'pending_oauth_token'
type PendingAuthSessionSummary = {
token: string
token_field: PendingAuthTokenField
provider: string
redirect?: string
}
type PendingOAuthCreateAccountResponse = {
access_token: string
refresh_token?: string
expires_in?: number
token_type?: string
}
const email = ref<string>('')
const password = ref<string>('')
const initialTurnstileToken = ref<string>('')
const promoCode = ref<string>('')
const invitationCode = ref<string>('')
const pendingAuthToken = ref<string>('')
const pendingAuthTokenField = ref<PendingAuthTokenField>('pending_auth_token')
const pendingProvider = ref<string>('')
const pendingRedirect = ref<string>('')
const pendingAdoptionDecision = ref<{
adoptDisplayName?: boolean
adoptAvatar?: boolean
} | null>(null)
const hasRegisterData = ref<boolean>(false)
// Public settings
@@ -228,6 +251,8 @@ const errors = ref({
// ==================== Lifecycle ====================
onMounted(async () => {
const activePendingSession = authStore.pendingAuthSession as PendingAuthSessionSummary | null
// Load registration data from sessionStorage
const registerDataStr = sessionStorage.getItem('register_data')
if (registerDataStr) {
@@ -238,10 +263,25 @@ onMounted(async () => {
initialTurnstileToken.value = registerData.turnstile_token || ''
promoCode.value = registerData.promo_code || ''
invitationCode.value = registerData.invitation_code || ''
pendingAuthToken.value = registerData.pending_auth_token || activePendingSession?.token || ''
pendingAuthTokenField.value = registerData.pending_auth_token_field || activePendingSession?.token_field || 'pending_auth_token'
pendingProvider.value = registerData.pending_provider || activePendingSession?.provider || ''
pendingRedirect.value = registerData.pending_redirect || activePendingSession?.redirect || ''
pendingAdoptionDecision.value = registerData.pending_adoption_decision
? {
adoptDisplayName: registerData.pending_adoption_decision.adopt_display_name === true,
adoptAvatar: registerData.pending_adoption_decision.adopt_avatar === true
}
: null
hasRegisterData.value = !!(email.value && password.value)
} catch {
hasRegisterData.value = false
}
} else if (activePendingSession) {
pendingAuthToken.value = activePendingSession.token
pendingAuthTokenField.value = activePendingSession.token_field
pendingProvider.value = activePendingSession.provider
pendingRedirect.value = activePendingSession.redirect || ''
}
// Load public settings
@@ -323,9 +363,10 @@ async function sendCode(): Promise<void> {
const response = await sendVerifyCode({
email: email.value,
[pendingAuthTokenField.value]: pendingAuthToken.value || undefined,
// 优先使用重发时新获取的 token因为初始 token 可能已被使用)
turnstile_token: resendTurnstileToken.value || initialTurnstileToken.value || undefined
})
} as Parameters<typeof sendVerifyCode>[0])
codeSent.value = true
startCountdown(response.countdown)
@@ -395,15 +436,32 @@ async function handleVerify(): Promise<void> {
return
}
// Register with verification code
await authStore.register({
email: email.value,
password: password.value,
verify_code: verifyCode.value.trim(),
turnstile_token: initialTurnstileToken.value || undefined,
promo_code: promoCode.value || undefined,
invitation_code: invitationCode.value || undefined
})
if (pendingProvider.value) {
const { data } = await apiClient.post<PendingOAuthCreateAccountResponse>(
'/auth/oauth/pending/create-account',
{
email: email.value,
password: password.value,
verify_code: verifyCode.value.trim(),
invitation_code: invitationCode.value || undefined,
adopt_display_name: pendingAdoptionDecision.value?.adoptDisplayName,
adopt_avatar: pendingAdoptionDecision.value?.adoptAvatar
}
)
persistOAuthTokenContext(data)
await authStore.setToken(data.access_token)
authStore.clearPendingAuthSession?.()
} else {
// Register with verification code
await authStore.register({
email: email.value,
password: password.value,
verify_code: verifyCode.value.trim(),
turnstile_token: initialTurnstileToken.value || undefined,
promo_code: promoCode.value || undefined,
invitation_code: invitationCode.value || undefined
})
}
// Clear session data
sessionStorage.removeItem('register_data')
@@ -412,7 +470,7 @@ async function handleVerify(): Promise<void> {
appStore.showSuccess(t('auth.accountCreatedSuccess', { siteName: siteName.value }))
// Redirect to dashboard
await router.push('/dashboard')
await router.push(pendingRedirect.value || '/dashboard')
} catch (error: unknown) {
errorMessage.value = buildAuthErrorMessage(error, {
fallback: t('auth.verifyFailed')