From fad1636f58b246837e2b4e7a77b726029bd46727 Mon Sep 17 00:00:00 2001 From: yaroslav8765 Date: Tue, 28 Apr 2026 14:38:42 +0300 Subject: [PATCH 1/8] fix: allow to resolve multiple 2fa calls for the verifyAuto calls --- custom/TwoFAModal.vue | 20 ++++++++++++++------ index.ts | 16 ++++++++++++---- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/custom/TwoFAModal.vue b/custom/TwoFAModal.vue index bb5e4e3..2385684 100644 --- a/custom/TwoFAModal.vue +++ b/custom/TwoFAModal.vue @@ -4,6 +4,7 @@

{{ customDialogTitle }}

+

You are confirming {{ sessionsIdsToResolve.length }} actions

{{ $t('Please enter your authenticator code') }}

@@ -51,6 +52,7 @@

{{$t('Passkey')}}

{{customDialogTitle}}

+

You are confirming {{ sessionsIdsToResolve.length }} actions

{{$t('Authenticate yourself using the button below')}}

-

You are confirming {{ sessionsIdsToResolve.length }} actions

+

+ {{$t('You are confirming')}} {{ sessionsIdsToResolve.length }} {{ sessionsIdsToResolve.length === 1 ? $t('action') : $t('actions') }} +

@@ -89,7 +91,9 @@ {{$t('Having trouble?')}}

-

You are confirming {{ sessionsIdsToResolve.length }} actions

+

+ {{$t('You are confirming')}} {{ sessionsIdsToResolve.length }} {{ sessionsIdsToResolve.length === 1 ? $t('action') : $t('actions') }} +

@@ -148,7 +152,7 @@ websocket.unsubscribeByPrefix(`/user2fa/`); websocket.subscribe(`/user2fa/${props.adminUser.pk}`, async (data: {sessionId: string}) => { if (!allowAddNewSessions) { - alert({message: 'Some process or user tries to add new actions to confirm. Action was blocked', variant: 'warning'}); + alert({message: t('Some process or user tries to add new actions to confirm. Action was blocked'), variant: 'warning'}); return; } sessionsIdsToResolve.value.push(data.sessionId); @@ -160,7 +164,7 @@ isAwaiting2FAResult.value = true; confirmationResult = await window.adminforthTwoFaModal.get2FaConfirmationResult(); } catch (error) { - console.error('Error during 2FA confirmation:', error); + console.error(t('Error during 2FA confirmation:', error)); } isAwaiting2FAResult.value = false; try { @@ -170,15 +174,15 @@ body: { confirmationResult, sessionsIds: sessionsIdsToResolve.value } }); if (!response.ok && response.error === 'No session ID or confirmation result'){ - alert({message: 'Verification session finished or cancelled.', variant: 'warning'}); + alert({message: t('Verification session finished or cancelled.'), variant: 'warning'}); } else if (!response.ok) { - alert({message: 'Verification failed', variant: 'danger'}); + alert({message: t('Verification failed'), variant: 'danger'}); } else if (response.ok) { - alert({message: 'Verification successful', variant: 'success'}); + alert({message: t('Verification successful'), variant: 'success'}); } sessionsIdsToResolve.value = []; } catch (error) { - console.error('Error resolving automatic 2FA verification:', error); + console.error(t('Error resolving automatic 2FA verification:', error)); } allowAddNewSessions = true; }); @@ -226,7 +230,7 @@ window.adminforthTwoFaModal = { get2FaConfirmationResult: (title?: string, verifyingCallback?: (confirmationResult: string) => Promise) => new Promise(async (resolve, reject) => { - if (modelShow.value) throw new Error('Modal is already open'); + if (modelShow.value) throw new Error(t('Modal is already open')); const skipAllowModal = await checkIfSkipAllowModal(); if (skipAllowModal) { resolve({ code: "123456" }); // dummy code @@ -303,12 +307,12 @@ } async function sendConfirmationResult(value: string) { - if (!resolveFn) throw new Error('Modal is not initialized properly'); + if (!resolveFn) throw new Error(t('Modal is not initialized properly')); if (verifyFn) { try { const ok = await verifyFn(value); if (!ok) { - rejectFn?.(new Error('Invalid code')); + rejectFn?.(new Error(t('Invalid code'))); return; } } catch (err) { @@ -393,7 +397,7 @@ } } } catch (error) { - console.error('Error checking passkeys:', error); + console.error(t('Error checking passkeys:', error)); // Fallback to TOTP if there's an error doesUserHavePasskeys.value = false; modalMode.value = "totp"; @@ -455,7 +459,7 @@ return false; } } catch (error) { - console.error('Error checking skip allow modal:', error); + console.error(t('Error checking skip allow modal:', error)); return false; } } diff --git a/custom/TwoFactorsConfirmation.vue b/custom/TwoFactorsConfirmation.vue index 1331b86..3c12871 100644 --- a/custom/TwoFactorsConfirmation.vue +++ b/custom/TwoFactorsConfirmation.vue @@ -299,7 +299,7 @@ } }); } catch (error) { - console.error('Error checking if user has passkeys:', error); + console.error(t('Error checking if user has passkeys:', error)); } } @@ -318,7 +318,7 @@ try { options = PublicKeyCredential.parseRequestOptionsFromJSON(_options); } catch (e) { - console.error('Error parsing request options:', e); + console.error(t('Error parsing request options:', e)); adminforth.alert({message: t('Error initiating passkey authentication.'), variant: 'warning'}); return; } @@ -345,14 +345,14 @@ method: 'POST', }); } catch (error) { - console.error('Error creating sign-in request:', error); + console.error(t('Error creating sign-in request:', error)); return; } if (response.ok === true) { return { _options: response.data, challengeId: response.challengeId }; } else { adminforth.alert({message: t('Error creating sign-in request.'), variant: 'warning'}); - codeError.value = 'Error creating sign-in request.'; + codeError.value = t('Error creating sign-in request.'); } } @@ -378,7 +378,7 @@ }); return credential; } catch (error) { - console.error('Error during authentication:', error); + console.error(t('Error during authentication:', error)); // Handle specific concurrent/pending request error cases gracefully const name = (error && (error.name || error.constructor?.name)) || ''; const message = (error && error.message) || ''; diff --git a/custom/TwoFactorsPasskeysSettings.vue b/custom/TwoFactorsPasskeysSettings.vue index 13618ed..13ad133 100644 --- a/custom/TwoFactorsPasskeysSettings.vue +++ b/custom/TwoFactorsPasskeysSettings.vue @@ -1,7 +1,7 @@