mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-24 16:29:45 +00:00
[auth] handle auth/requires-recent-login for account deletion and password updates (#6109)
## Summary Implemented error recovery system to handle Firebase `auth/requires-recent-login` errors when deleting accounts or updating passwords. https://github.com/user-attachments/assets/92a79e2a-cff5-4b18-b529-dbaf5f2303f2 ## Changes - **What**: Added [ErrorRecoveryStrategy pattern](https://firebase.google.com/docs/auth/web/manage-users#re-authenticate_a_user) to `useErrorHandling` composable with automatic retry logic for sensitive Firebase operations - **Breaking**: None - recovery strategies are optional, all existing code unchanged ## Technical Details Firebase enforces [reauthentication](https://firebase.google.com/docs/reference/js/auth#autherrorcodes) for security-sensitive operations (account deletion, password changes) after ~5 minutes of inactivity. Previously these operations failed with cryptic error messages. New flow: 1. Operation throws `auth/requires-recent-login` 2. Recovery strategy shows confirmation dialog 3. User logs out and re-authenticates 4. Operation automatically retries ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6109-auth-handle-auth-requires-recent-login-for-account-deletion-and-password-updates-28f6d73d36508119abf4ce30eecea976) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
import { FirebaseError } from 'firebase/app'
|
||||
import { AuthErrorCodes } from 'firebase/auth'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { useErrorHandling } from '@/composables/useErrorHandling'
|
||||
import type { ErrorRecoveryStrategy } from '@/composables/useErrorHandling'
|
||||
import { t } from '@/i18n'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
|
||||
import { usdToMicros } from '@/utils/formatUtil'
|
||||
|
||||
@@ -122,6 +125,47 @@ export const useFirebaseAuthActions = () => {
|
||||
reportError
|
||||
)
|
||||
|
||||
/**
|
||||
* Recovery strategy for Firebase auth/requires-recent-login errors.
|
||||
* Prompts user to reauthenticate and retries the operation after successful login.
|
||||
*/
|
||||
const createReauthenticationRecovery = <
|
||||
TArgs extends unknown[],
|
||||
TReturn
|
||||
>(): ErrorRecoveryStrategy<TArgs, TReturn> => {
|
||||
const dialogService = useDialogService()
|
||||
|
||||
return {
|
||||
shouldHandle: (error: unknown) =>
|
||||
error instanceof FirebaseError &&
|
||||
error.code === AuthErrorCodes.CREDENTIAL_TOO_OLD_LOGIN_AGAIN,
|
||||
|
||||
recover: async (
|
||||
_error: unknown,
|
||||
retry: (...args: TArgs) => Promise<TReturn> | TReturn,
|
||||
args: TArgs
|
||||
) => {
|
||||
const confirmed = await dialogService.confirm({
|
||||
title: t('auth.reauthRequired.title'),
|
||||
message: t('auth.reauthRequired.message'),
|
||||
type: 'default'
|
||||
})
|
||||
|
||||
if (!confirmed) {
|
||||
return
|
||||
}
|
||||
|
||||
await authStore.logout()
|
||||
|
||||
const signedIn = await dialogService.showSignInDialog()
|
||||
|
||||
if (signedIn) {
|
||||
await retry(...args)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updatePassword = wrapWithErrorHandlingAsync(
|
||||
async (newPassword: string) => {
|
||||
await authStore.updatePassword(newPassword)
|
||||
@@ -132,18 +176,25 @@ export const useFirebaseAuthActions = () => {
|
||||
life: 5000
|
||||
})
|
||||
},
|
||||
reportError
|
||||
reportError,
|
||||
undefined,
|
||||
[createReauthenticationRecovery<[string], void>()]
|
||||
)
|
||||
|
||||
const deleteAccount = wrapWithErrorHandlingAsync(async () => {
|
||||
await authStore.deleteAccount()
|
||||
toastStore.add({
|
||||
severity: 'success',
|
||||
summary: t('auth.deleteAccount.success'),
|
||||
detail: t('auth.deleteAccount.successDetail'),
|
||||
life: 5000
|
||||
})
|
||||
}, reportError)
|
||||
const deleteAccount = wrapWithErrorHandlingAsync(
|
||||
async () => {
|
||||
await authStore.deleteAccount()
|
||||
toastStore.add({
|
||||
severity: 'success',
|
||||
summary: t('auth.deleteAccount.success'),
|
||||
detail: t('auth.deleteAccount.successDetail'),
|
||||
life: 5000
|
||||
})
|
||||
},
|
||||
reportError,
|
||||
undefined,
|
||||
[createReauthenticationRecovery<[], void>()]
|
||||
)
|
||||
|
||||
return {
|
||||
logout,
|
||||
|
||||
Reference in New Issue
Block a user