[feat] Add account deletion functionality to UserPanel component (#5216)

This commit is contained in:
Yoland Yan
2025-08-29 15:29:20 -07:00
committed by GitHub
parent 2bf92a0e57
commit 23d0362267
13 changed files with 141 additions and 10 deletions

View File

@@ -57,14 +57,23 @@
class="w-8 h-8 mt-4"
style="--pc-spinner-color: #000"
/>
<Button
v-else
class="mt-4 w-32"
severity="secondary"
:label="$t('auth.signOut.signOut')"
icon="pi pi-sign-out"
@click="handleSignOut"
/>
<div v-else class="mt-4 flex flex-col gap-2">
<Button
class="w-32"
severity="secondary"
:label="$t('auth.signOut.signOut')"
icon="pi pi-sign-out"
@click="handleSignOut"
/>
<Button
v-if="!isApiKeyLogin"
class="w-32"
severity="danger"
:label="$t('auth.deleteAccount.deleteAccount')"
icon="pi pi-trash"
@click="handleDeleteAccount"
/>
</div>
</div>
<!-- Login Section -->
@@ -100,6 +109,7 @@ const dialogService = useDialogService()
const {
loading,
isLoggedIn,
isApiKeyLogin,
isEmailProvider,
userDisplayName,
userEmail,
@@ -107,6 +117,7 @@ const {
providerName,
providerIcon,
handleSignOut,
handleSignIn
handleSignIn,
handleDeleteAccount
} = useCurrentUser()
</script>

View File

@@ -1,5 +1,8 @@
import { computed } from 'vue'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { t } from '@/i18n'
import { useDialogService } from '@/services/dialogService'
import { useApiKeyAuthStore } from '@/stores/apiKeyAuthStore'
import { useCommandStore } from '@/stores/commandStore'
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
@@ -8,6 +11,8 @@ export const useCurrentUser = () => {
const authStore = useFirebaseAuthStore()
const commandStore = useCommandStore()
const apiKeyStore = useApiKeyAuthStore()
const dialogService = useDialogService()
const { deleteAccount } = useFirebaseAuthActions()
const firebaseUser = computed(() => authStore.currentUser)
const isApiKeyLogin = computed(() => apiKeyStore.isAuthenticated)
@@ -85,6 +90,18 @@ export const useCurrentUser = () => {
await commandStore.execute('Comfy.User.OpenSignInDialog')
}
const handleDeleteAccount = async () => {
const confirmed = await dialogService.confirm({
title: t('auth.deleteAccount.confirmTitle'),
message: t('auth.deleteAccount.confirmMessage'),
type: 'delete'
})
if (confirmed) {
await deleteAccount()
}
}
return {
loading: authStore.loading,
isLoggedIn,
@@ -96,6 +113,7 @@ export const useCurrentUser = () => {
providerName,
providerIcon,
handleSignOut,
handleSignIn
handleSignIn,
handleDeleteAccount
}
}

View File

@@ -135,6 +135,16 @@ export const useFirebaseAuthActions = () => {
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)
return {
logout,
sendPasswordReset,
@@ -146,6 +156,7 @@ export const useFirebaseAuthActions = () => {
signInWithEmail,
signUpWithEmail,
updatePassword,
deleteAccount,
accessError
}
}

View File

@@ -27,6 +27,15 @@
"title": "مفتاح API",
"whitelistInfo": "حول المواقع غير المدرجة في القائمة البيضاء"
},
"deleteAccount": {
"cancel": "إلغاء",
"confirm": "حذف الحساب",
"confirmMessage": "هل أنت متأكد أنك تريد حذف حسابك؟ لا يمكن التراجع عن هذا الإجراء وسيتم حذف جميع بياناتك نهائيًا.",
"confirmTitle": "حذف الحساب",
"deleteAccount": "حذف الحساب",
"success": "تم حذف الحساب",
"successDetail": "تم حذف حسابك بنجاح."
},
"login": {
"andText": "و",
"confirmPasswordLabel": "تأكيد كلمة المرور",

View File

@@ -1601,6 +1601,15 @@
"passwordUpdate": {
"success": "Password Updated",
"successDetail": "Your password has been updated successfully"
},
"deleteAccount": {
"deleteAccount": "Delete Account",
"confirmTitle": "Delete Account",
"confirmMessage": "Are you sure you want to delete your account? This action cannot be undone and will permanently remove all your data.",
"confirm": "Delete Account",
"cancel": "Cancel",
"success": "Account Deleted",
"successDetail": "Your account has been successfully deleted."
}
},
"validation": {

View File

@@ -27,6 +27,15 @@
"title": "Clave API",
"whitelistInfo": "Acerca de los sitios no incluidos en la lista blanca"
},
"deleteAccount": {
"cancel": "Cancelar",
"confirm": "Eliminar cuenta",
"confirmMessage": "¿Estás seguro de que deseas eliminar tu cuenta? Esta acción no se puede deshacer y eliminará permanentemente todos tus datos.",
"confirmTitle": "Eliminar cuenta",
"deleteAccount": "Eliminar cuenta",
"success": "Cuenta eliminada",
"successDetail": "Tu cuenta ha sido eliminada exitosamente."
},
"login": {
"andText": "y",
"confirmPasswordLabel": "Confirmar contraseña",

View File

@@ -27,6 +27,15 @@
"title": "Clé API",
"whitelistInfo": "À propos des sites non autorisés"
},
"deleteAccount": {
"cancel": "Annuler",
"confirm": "Supprimer le compte",
"confirmMessage": "Êtes-vous sûr de vouloir supprimer votre compte ? Cette action est irréversible et supprimera définitivement toutes vos données.",
"confirmTitle": "Supprimer le compte",
"deleteAccount": "Supprimer le compte",
"success": "Compte supprimé",
"successDetail": "Votre compte a été supprimé avec succès."
},
"login": {
"andText": "et",
"confirmPasswordLabel": "Confirmer le mot de passe",

View File

@@ -27,6 +27,15 @@
"title": "APIキー",
"whitelistInfo": "ホワイトリストに登録されていないサイトについて"
},
"deleteAccount": {
"cancel": "キャンセル",
"confirm": "アカウントを削除",
"confirmMessage": "本当にアカウントを削除しますか?この操作は元に戻せず、すべてのデータが完全に削除されます。",
"confirmTitle": "アカウントを削除",
"deleteAccount": "アカウントを削除",
"success": "アカウントが削除されました",
"successDetail": "アカウントは正常に削除されました。"
},
"login": {
"andText": "および",
"confirmPasswordLabel": "パスワードの確認",

View File

@@ -27,6 +27,15 @@
"title": "API 키",
"whitelistInfo": "비허용 사이트에 대하여"
},
"deleteAccount": {
"cancel": "취소",
"confirm": "계정 삭제",
"confirmMessage": "정말로 계정을 삭제하시겠습니까? 이 작업은 되돌릴 수 없으며 모든 데이터가 영구적으로 삭제됩니다.",
"confirmTitle": "계정 삭제",
"deleteAccount": "계정 삭제",
"success": "계정이 삭제되었습니다",
"successDetail": "계정이 성공적으로 삭제되었습니다."
},
"login": {
"andText": "및",
"confirmPasswordLabel": "비밀번호 확인",

View File

@@ -27,6 +27,15 @@
"title": "API-ключ",
"whitelistInfo": "О не включённых в белый список сайтах"
},
"deleteAccount": {
"cancel": "Отмена",
"confirm": "Удалить аккаунт",
"confirmMessage": "Вы уверены, что хотите удалить свой аккаунт? Это действие необратимо и приведёт к безвозвратному удалению всех ваших данных.",
"confirmTitle": "Удалить аккаунт",
"deleteAccount": "Удалить аккаунт",
"success": "Аккаунт удалён",
"successDetail": "Ваш аккаунт был успешно удалён."
},
"login": {
"andText": "и",
"confirmPasswordLabel": "Подтвердите пароль",

View File

@@ -27,6 +27,15 @@
"title": "API 金鑰",
"whitelistInfo": "關於未列入白名單的網站"
},
"deleteAccount": {
"cancel": "取消",
"confirm": "刪除帳號",
"confirmMessage": "您確定要刪除您的帳號嗎?此操作無法復原,且將永久移除您所有的資料。",
"confirmTitle": "刪除帳號",
"deleteAccount": "刪除帳號",
"success": "帳號已刪除",
"successDetail": "您的帳號已成功刪除。"
},
"login": {
"andText": "以及",
"confirmPasswordLabel": "確認密碼",

View File

@@ -27,6 +27,15 @@
"title": "API 密钥",
"whitelistInfo": "关于非白名单网站"
},
"deleteAccount": {
"cancel": "取消",
"confirm": "删除账户",
"confirmMessage": "您确定要删除您的账户吗?此操作无法撤销,并且会永久删除您的所有数据。",
"confirmTitle": "删除账户",
"deleteAccount": "删除账户",
"success": "账户已删除",
"successDetail": "您的账户已成功删除。"
},
"login": {
"andText": "和",
"confirmPasswordLabel": "确认密码",

View File

@@ -8,6 +8,7 @@ import {
type UserCredential,
browserLocalPersistence,
createUserWithEmailAndPassword,
deleteUser,
onAuthStateChanged,
sendPasswordResetEmail,
setPersistence,
@@ -287,6 +288,14 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
await updatePassword(currentUser.value, newPassword)
}
/** Delete the current user account */
const _deleteAccount = async (): Promise<void> => {
if (!currentUser.value) {
throw new FirebaseAuthStoreError(t('toastMessages.userNotAuthenticated'))
}
await deleteUser(currentUser.value)
}
const addCredits = async (
requestBodyContent: CreditPurchasePayload
): Promise<CreditPurchaseResponse> => {
@@ -385,6 +394,7 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
accessBillingPortal,
sendPasswordReset,
updatePassword: _updatePassword,
deleteAccount: _deleteAccount,
getAuthHeader
}
})