diff --git a/src/components/device-management/device-management.ts b/src/components/device-management/device-management.ts index e30bd60..2e71647 100644 --- a/src/components/device-management/device-management.ts +++ b/src/components/device-management/device-management.ts @@ -1,4 +1,3 @@ -// import { getCorrectDOM } from '../../utils/html.utils'; // Unused import import Services from '../../services/service'; import { addressToWords } from '../../utils/sp-address.utils'; diff --git a/src/pages/birthday-setup/birthday-setup.ts b/src/pages/birthday-setup/birthday-setup.ts index 7c512b2..8a1e57f 100644 --- a/src/pages/birthday-setup/birthday-setup.ts +++ b/src/pages/birthday-setup/birthday-setup.ts @@ -3,6 +3,8 @@ * Mise à jour de la date anniversaire et scan des blocs */ +import { checkPBKDF2Key, checkWalletWithRetries } from '../../utils/prerequisites.utils'; + document.addEventListener('DOMContentLoaded', async () => { console.log('🎂 Birthday setup page loaded'); @@ -47,32 +49,9 @@ document.addEventListener('DOMContentLoaded', async () => { updateStatus('🔍 Vérification des prérequis...', 'loading'); updateProgress(20); - // Vérifier que le PBKDF2 key existe d'abord (prérequis le plus basique) dans le store pbkdf2keys - const { SecureCredentialsService } = await import('../../services/secure-credentials.service'); - const secureCredentials = SecureCredentialsService.getInstance(); - - let pbkdf2KeyFound = false; - const securityModes = ['none', 'otp', 'password', 'os', 'proton-pass']; - for (const mode of securityModes) { - try { - // Vérifier d'abord silencieusement si une clé existe dans le store pbkdf2keys - const hasKey = await secureCredentials.hasPBKDF2Key(mode as any); - if (hasKey) { - // Si une clé existe, essayer de la récupérer - const key = await secureCredentials.retrievePBKDF2Key(mode as any); - if (key) { - pbkdf2KeyFound = true; - console.log(`✅ PBKDF2 key found in pbkdf2keys store for security mode: ${mode}`); - break; - } - } - } catch (error) { - // Continue to next mode - console.log(`⚠️ No PBKDF2 key found in pbkdf2keys store for mode ${mode}`); - } - } - - if (!pbkdf2KeyFound) { + // Vérifier que le PBKDF2 key existe d'abord (prérequis le plus basique) + const pbkdf2KeyResult = await checkPBKDF2Key(); + if (!pbkdf2KeyResult) { console.log('⚠️ PBKDF2 key not found in pbkdf2keys store, redirecting to security-setup...'); updateStatus('⚠️ Redirection vers la configuration de sécurité...', 'loading'); setTimeout(() => { @@ -82,28 +61,16 @@ document.addEventListener('DOMContentLoaded', async () => { } // Vérifier que le wallet existe en base (avec plusieurs tentatives pour gérer les problèmes de synchronisation) - let wallet = await services.getDeviceFromDatabase(); + const wallet = await checkWalletWithRetries(); if (!wallet) { - console.log('⚠️ Wallet not found, waiting for database synchronization...'); - // Attendre un peu pour la synchronisation de la base de données - for (let attempt = 0; attempt < 5; attempt++) { - await new Promise(resolve => setTimeout(resolve, 500)); - wallet = await services.getDeviceFromDatabase(); - if (wallet) { - console.log(`✅ Wallet found after ${attempt + 1} attempts`); - break; - } - } - - if (!wallet) { - console.log('⚠️ Wallet still not found after retries, redirecting to wallet-setup...'); - updateStatus('⚠️ Redirection vers la configuration du wallet...', 'loading'); - setTimeout(() => { - window.location.href = '/src/pages/wallet-setup/wallet-setup.html'; - }, 1000); - return; - } + console.log('⚠️ Wallet still not found after retries, redirecting to wallet-setup...'); + updateStatus('⚠️ Redirection vers la configuration du wallet...', 'loading'); + setTimeout(() => { + window.location.href = '/src/pages/wallet-setup/wallet-setup.html'; + }, 1000); + return; } + // Vérifier que le wallet contient bien les données attendues if (wallet.sp_wallet?.birthday !== undefined) { console.log('✅ Wallet found in database with birthday:', wallet.sp_wallet.birthday); @@ -112,7 +79,7 @@ document.addEventListener('DOMContentLoaded', async () => { } // Vérifier que tous les prérequis sont remplis - const prerequisitesOk = wallet && pbkdf2KeyFound; + const prerequisitesOk = wallet && pbkdf2KeyResult; if (prerequisitesOk) { console.log('✅ All prerequisites verified'); } else { diff --git a/src/pages/block-sync/block-sync.ts b/src/pages/block-sync/block-sync.ts index b02d68e..917ca91 100644 --- a/src/pages/block-sync/block-sync.ts +++ b/src/pages/block-sync/block-sync.ts @@ -1,3 +1,5 @@ +import { checkPBKDF2Key, checkWalletWithRetries } from '../../utils/prerequisites.utils'; + document.addEventListener("DOMContentLoaded", async () => { console.log("🔄 Block sync page loaded"); @@ -42,29 +44,9 @@ document.addEventListener("DOMContentLoaded", async () => { updateStatus('🔍 Vérification des prérequis...', 'loading'); updateProgress(10); - // Vérifier que le PBKDF2 key existe d'abord (prérequis le plus basique) dans le store pbkdf2keys - const { SecureCredentialsService } = await import('../../services/secure-credentials.service'); - const secureCredentials = SecureCredentialsService.getInstance(); - - let pbkdf2KeyFound = false; - const securityModes = ['none', 'otp', 'password', 'os', 'proton-pass']; - for (const mode of securityModes) { - try { - const hasKey = await secureCredentials.hasPBKDF2Key(mode as any); - if (hasKey) { - const key = await secureCredentials.retrievePBKDF2Key(mode as any); - if (key) { - pbkdf2KeyFound = true; - console.log(`✅ PBKDF2 key found in pbkdf2keys store for security mode: ${mode}`); - break; - } - } - } catch (error) { - console.log(`⚠️ No PBKDF2 key found in pbkdf2keys store for mode ${mode}`); - } - } - - if (!pbkdf2KeyFound) { + // Vérifier que le PBKDF2 key existe d'abord (prérequis le plus basique) + const pbkdf2KeyResult = await checkPBKDF2Key(); + if (!pbkdf2KeyResult) { console.log('⚠️ PBKDF2 key not found in pbkdf2keys store, redirecting to security-setup...'); updateStatus('⚠️ Redirection vers la configuration de sécurité...', 'loading'); setTimeout(() => { @@ -73,71 +55,15 @@ document.addEventListener("DOMContentLoaded", async () => { return; } - // Étape 2: Initialisation des services - updateStatus('🔄 Initialisation des services...', 'loading'); - updateProgress(20); - - const { default: Services } = await import('../../services/service'); - if (!Services) { - throw new Error('Services class not found in default export'); - } - - console.log('🔄 Waiting for services to be ready...'); - let attempts = 0; - const maxAttempts = 30; - const delayMs = 2000; - - let services; - while (attempts < maxAttempts) { - try { - console.log(`🔄 Attempting to get services (attempt ${attempts + 1}/${maxAttempts})...`); - services = await Services.getInstance(); - console.log('✅ Services initialized successfully'); - break; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - console.log(`⏳ Services not ready yet (attempt ${attempts + 1}/${maxAttempts}):`, errorMessage); - - // Si c'est une erreur de mémoire, arrêter immédiatement - if (errorMessage.includes('Out of memory') || errorMessage.includes('insufficient memory')) { - console.error('🚫 Memory error detected - stopping retry attempts'); - updateStatus('❌ Erreur: Mémoire insuffisante. Veuillez actualiser la page.', 'error'); - throw new Error('WebAssembly initialization failed due to insufficient memory. Please refresh the page.'); - } - - attempts++; - if (attempts >= maxAttempts) { - throw new Error(`Services failed to initialize after ${maxAttempts} attempts.`); - } - await new Promise(resolve => setTimeout(resolve, delayMs)); - } - } - - if (!services) { - throw new Error('Services not initialized'); - } - // Vérifier que le wallet existe en base (avec plusieurs tentatives pour gérer les problèmes de synchronisation) - let wallet = await services.getDeviceFromDatabase(); + const wallet = await checkWalletWithRetries(); if (!wallet) { - console.log('⚠️ Wallet not found, waiting for database synchronization...'); - for (let attempt = 0; attempt < 5; attempt++) { - await new Promise(resolve => setTimeout(resolve, 500)); - wallet = await services.getDeviceFromDatabase(); - if (wallet) { - console.log(`✅ Wallet found after ${attempt + 1} attempts`); - break; - } - } - - if (!wallet) { - console.log('⚠️ Wallet still not found after retries, redirecting to wallet-setup...'); - updateStatus('⚠️ Redirection vers la configuration du wallet...', 'loading'); - setTimeout(() => { - window.location.href = '/src/pages/wallet-setup/wallet-setup.html'; - }, 1000); - return; - } + console.log('⚠️ Wallet still not found after retries, redirecting to wallet-setup...'); + updateStatus('⚠️ Redirection vers la configuration du wallet...', 'loading'); + setTimeout(() => { + window.location.href = '/src/pages/wallet-setup/wallet-setup.html'; + }, 1000); + return; } // Vérifier que le wallet contient bien les données attendues diff --git a/src/pages/home/home.ts b/src/pages/home/home.ts index 59372b0..249a9ce 100755 --- a/src/pages/home/home.ts +++ b/src/pages/home/home.ts @@ -5,6 +5,7 @@ import { addSubscription } from '../../utils/subscription.utils'; import { displayEmojis, generateCreateBtn, addressToEmoji, prepareAndSendPairingTx } from '../../utils/sp-address.utils'; import { getCorrectDOM } from '../../utils/html.utils'; import { IframePairingComponent } from '../../components/iframe-pairing/iframe-pairing'; +import { checkPBKDF2Key, checkWalletWithRetries } from '../../utils/prerequisites.utils'; // Extend WindowEventMap to include custom events declare global { @@ -36,30 +37,8 @@ export async function initHomePage(): Promise { const deviceReader = DeviceReaderService.getInstance(); // Vérifier que le PBKDF2 key existe d'abord (prérequis le plus basique) dans le store pbkdf2keys - const secureCredentials = SecureCredentialsService.getInstance(); - - let pbkdf2KeyFound = false; - const securityModes = ['none', 'otp', 'password', 'os', 'proton-pass']; - for (const mode of securityModes) { - try { - // Vérifier d'abord silencieusement si une clé existe dans le store pbkdf2keys - const hasKey = await secureCredentials.hasPBKDF2Key(mode as any); - if (hasKey) { - // Si une clé existe, essayer de la récupérer - const key = await secureCredentials.retrievePBKDF2Key(mode as any); - if (key) { - pbkdf2KeyFound = true; - console.log(`✅ PBKDF2 key found in pbkdf2keys store for security mode: ${mode}`); - break; - } - } - } catch (error) { - // Continue to next mode - console.log(`⚠️ No PBKDF2 key found in pbkdf2keys store for mode ${mode}`); - } - } - - if (!pbkdf2KeyFound) { + const pbkdf2KeyResult = await checkPBKDF2Key(); + if (!pbkdf2KeyResult) { console.log('⚠️ PBKDF2 key not found in pbkdf2keys store, redirecting to security-setup...'); setTimeout(() => { window.location.href = '/src/pages/security-setup/security-setup.html'; @@ -68,26 +47,13 @@ export async function initHomePage(): Promise { } // Vérifier que le wallet existe en base (avec plusieurs tentatives pour gérer les problèmes de synchronisation) - let wallet = await deviceReader.getDeviceFromDatabase(); + const wallet = await checkWalletWithRetries(); if (!wallet) { - console.log('⚠️ Wallet not found, waiting for database synchronization...'); - // Attendre un peu pour la synchronisation de la base de données - for (let attempt = 0; attempt < 5; attempt++) { - await new Promise(resolve => setTimeout(resolve, 500)); - wallet = await deviceReader.getDeviceFromDatabase(); - if (wallet) { - console.log(`✅ Wallet found after ${attempt + 1} attempts`); - break; - } - } - - if (!wallet) { - console.log('⚠️ Wallet still not found after retries, redirecting to wallet-setup...'); - setTimeout(() => { - window.location.href = '/src/pages/wallet-setup/wallet-setup.html'; - }, 1000); - return; - } + console.log('⚠️ Wallet still not found after retries, redirecting to wallet-setup...'); + setTimeout(() => { + window.location.href = '/src/pages/wallet-setup/wallet-setup.html'; + }, 1000); + return; } // Vérifier que le wallet contient bien les données attendues diff --git a/src/pages/wallet-setup/wallet-setup.ts b/src/pages/wallet-setup/wallet-setup.ts index 89d073f..876f384 100644 --- a/src/pages/wallet-setup/wallet-setup.ts +++ b/src/pages/wallet-setup/wallet-setup.ts @@ -4,6 +4,7 @@ */ import { DATABASE_CONFIG } from '../../services/database-config'; +import { checkPBKDF2Key } from '../../utils/prerequisites.utils'; document.addEventListener('DOMContentLoaded', async () => { console.log('💰 Wallet setup page loaded'); @@ -52,7 +53,6 @@ document.addEventListener('DOMContentLoaded', async () => { updateProgress(10); let services: any; // Déclarer services au niveau supérieur - let currentMode: string | null = null; // Déclarer currentMode au niveau supérieur try { console.log('🔄 Importing services...'); @@ -123,31 +123,8 @@ document.addEventListener('DOMContentLoaded', async () => { // On vérifie que la clé PBKDF2 existe dans le store pbkdf2keys console.log('🔐 Checking for existing PBKDF2 key in pbkdf2keys store...'); - const { SecureCredentialsService } = await import('../../services/secure-credentials.service'); - const secureCredentialsService = SecureCredentialsService.getInstance(); - - // Vérifier que la clé PBKDF2 existe pour au moins un mode de sécurité dans le store pbkdf2keys - const securityModes: Array<'otp' | 'password' | 'none' | 'os' | 'proton-pass'> = - ['none', 'otp', 'password', 'os', 'proton-pass']; - - for (const mode of securityModes) { - try { - const hasKey = await secureCredentialsService.hasPBKDF2Key(mode); - if (hasKey) { - const key = await secureCredentialsService.retrievePBKDF2Key(mode); - if (key) { - currentMode = mode; - console.log(`✅ PBKDF2 key found in pbkdf2keys store for security mode: ${mode}`); - break; - } - } - } catch (error) { - // Continue to next mode - console.log(`⚠️ No PBKDF2 key found in pbkdf2keys store for mode ${mode}`); - } - } - - if (!currentMode) { + const pbkdf2KeyResult = await checkPBKDF2Key(); + if (!pbkdf2KeyResult) { console.log('⚠️ No PBKDF2 key found in pbkdf2keys store, redirecting to security-setup...'); updateStatus('⚠️ Redirection vers la configuration de sécurité...', 'loading'); setTimeout(() => { @@ -156,6 +133,7 @@ document.addEventListener('DOMContentLoaded', async () => { return; } + const currentMode = pbkdf2KeyResult.mode; console.log('✅ Prerequisites verified: PBKDF2 key found in pbkdf2keys store for mode:', currentMode); // Étape 3: Sauvegarde du wallet avec état birthday_waiting @@ -188,7 +166,7 @@ document.addEventListener('DOMContentLoaded', async () => { // Récupérer la clé PBKDF2 existante pour le mode détecté // IMPORTANT: Ne PAS générer de nouvelle clé, utiliser celle qui existe console.log('🔐 Retrieving existing PBKDF2 key for security mode:', currentMode); - const pbkdf2Key = await secureCredentialsService.retrievePBKDF2Key(currentMode as any); + const pbkdf2Key = pbkdf2KeyResult.key; if (!pbkdf2Key) { console.error('❌ CRITICAL: Failed to retrieve PBKDF2 key for mode:', currentMode); updateStatus('❌ Erreur: Impossible de récupérer la clé de chiffrement.', 'error'); @@ -394,7 +372,7 @@ document.addEventListener('DOMContentLoaded', async () => { // TEST: Déchiffrer le wallet pour valider que ça fonctionne console.log('🔐 TEST: Attempting to decrypt wallet to validate encryption...'); try { - const pbkdf2KeyTest = await secureCredentialsService.retrievePBKDF2Key(currentMode as any); + const pbkdf2KeyTest = pbkdf2KeyResult.key; if (!pbkdf2KeyTest) { console.error('❌ TEST: Failed to retrieve PBKDF2 key for decryption test'); } else { diff --git a/src/router.ts b/src/router.ts index 00ab0ae..90e9ef8 100755 --- a/src/router.ts +++ b/src/router.ts @@ -1,15 +1,14 @@ // CSS is loaded via HTML link tag -/*import { initChat } from '../src/pages/chat/chat';*/ import Database from './services/database.service'; import Services from './services/service'; import TokenService from './services/token'; import { cleanSubscriptions } from './utils/subscription.utils'; import { LoginComponent } from './pages/home/home-component'; -// import { prepareAndSendPairingTx } from './utils/sp-address.utils'; // Unused import import ModalService from './services/modal.service'; import { MessageType } from './models/process.model'; import { splitPrivateData, isValid32ByteHex } from './utils/service.utils'; import { MerkleProofResult } from 'pkg/sdk_client'; +import { checkPBKDF2Key } from './utils/prerequisites.utils'; const routes: { [key: string]: string } = { home: '/src/pages/home/home.html', @@ -44,31 +43,9 @@ export async function checkStorageStateAndNavigate(): Promise { const deviceReader = DeviceReaderService.getInstance(); // Vérifier si une clé PBKDF2 existe (vérification la plus légère) - const { SecureCredentialsService } = await import('./services/secure-credentials.service'); - const secureCredentialsService = SecureCredentialsService.getInstance(); + const pbkdf2KeyResult = await checkPBKDF2Key(); - const allSecurityModes: Array<'otp' | 'password' | 'none' | 'os' | 'proton-pass'> = - ['none', 'otp', 'password', 'os', 'proton-pass']; - - let hasPBKDF2Key = false; - for (const mode of allSecurityModes) { - try { - const hasKey = await secureCredentialsService.hasPBKDF2Key(mode); - if (hasKey) { - const key = await secureCredentialsService.retrievePBKDF2Key(mode); - if (key) { - hasPBKDF2Key = true; - console.log(`🔐 PBKDF2 key found for mode: ${mode}`); - break; - } - } - } catch (error) { - // Mode non disponible, continuer - console.log(`⚠️ No PBKDF2 key found for mode ${mode}`); - } - } - - if (!hasPBKDF2Key) { + if (!pbkdf2KeyResult) { // Aucune clé PBKDF2 trouvée, commencer par la configuration de sécurité console.log('🔐 No PBKDF2 key found, navigating to security-setup'); await navigate('security-setup'); @@ -86,7 +63,7 @@ export async function checkStorageStateAndNavigate(): Promise { // Vérifier si la date anniversaire est configurée (wallet avec birthday > 0) if (device.sp_wallet.birthday && device.sp_wallet.birthday > 0) { console.log('🎂 Birthday is configured, checking pairing status...'); - + // Vérifier l'état du pairing (nécessite Services mais seulement si tout est prêt) try { const services = await Services.getInstance(); diff --git a/src/services/modal.service.ts b/src/services/modal.service.ts index 0aed620..11e2d8d 100755 --- a/src/services/modal.service.ts +++ b/src/services/modal.service.ts @@ -3,7 +3,6 @@ import modalScript from '../components/login-modal/login-modal.js?raw'; import validationModalStyle from '../components/validation-modal/validation-modal.css?raw'; import Services from './service'; import { navigate } from '../router'; -// import { init } from '../router'; // Unused import import { addressToEmoji } from '../utils/sp-address.utils'; import { RoleDefinition } from 'pkg/sdk_client'; import { initValidationModal } from '../components/validation-modal/validation-modal'; diff --git a/src/services/service.ts b/src/services/service.ts index 64c86fb..e05c9a2 100755 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -1,9 +1,6 @@ -// import { INotification } from '~/models/notification.model'; // Unused import -// import { IProcess } from '~/models/process.model'; // Unused import import { initWebsocket, sendMessage } from '../websockets'; import { memoryManager } from './memory-manager'; import { secureLogger } from './secure-logger'; -// import { secureKeyManager } from './secure-key-manager'; import { ApiReturn, Device, @@ -20,9 +17,7 @@ import { } from '../../pkg/sdk_client'; import ModalService from './modal.service'; import Database from './database.service'; -// import { navigate } from '../router'; // Unused import import { storeData, retrieveData } from './storage.service'; -// import { testData } from './storage.service'; // Unused import import { BackUp } from '../models/backup.model'; import { DATABASE_CONFIG } from './database-config'; diff --git a/src/utils/prerequisites.utils.ts b/src/utils/prerequisites.utils.ts new file mode 100644 index 0000000..ef534cc --- /dev/null +++ b/src/utils/prerequisites.utils.ts @@ -0,0 +1,83 @@ +/** + * Utilitaires pour vérifier les prérequis de l'application + * Centralise la logique de vérification pour éviter la duplication + */ + +import { SecureCredentialsService } from '../services/secure-credentials.service'; +import { DeviceReaderService } from '../services/device-reader.service'; + +export type SecurityMode = 'none' | 'otp' | 'password' | 'os' | 'proton-pass'; + +const ALL_SECURITY_MODES: SecurityMode[] = ['none', 'otp', 'password', 'os', 'proton-pass']; + +/** + * Vérifie si une clé PBKDF2 existe dans le store pbkdf2keys + * @returns La clé PBKDF2 trouvée et le mode de sécurité associé, ou null si aucune clé n'est trouvée + */ +export async function checkPBKDF2Key(): Promise<{ key: string; mode: SecurityMode } | null> { + const secureCredentialsService = SecureCredentialsService.getInstance(); + + for (const mode of ALL_SECURITY_MODES) { + try { + const hasKey = await secureCredentialsService.hasPBKDF2Key(mode); + if (hasKey) { + const key = await secureCredentialsService.retrievePBKDF2Key(mode); + if (key) { + console.log(`✅ PBKDF2 key found in pbkdf2keys store for security mode: ${mode}`); + return { key, mode }; + } + } + } catch (error) { + // Continue to next mode + console.log(`⚠️ No PBKDF2 key found in pbkdf2keys store for mode ${mode}`); + } + } + + return null; +} + +/** + * Vérifie si le wallet existe en base de données avec retries pour gérer la synchronisation + * @param maxAttempts Nombre maximum de tentatives + * @param delayMs Délai entre les tentatives en millisecondes + * @returns Le wallet trouvé ou null si non trouvé après toutes les tentatives + */ +export async function checkWalletWithRetries( + maxAttempts: number = 5, + delayMs: number = 500 +): Promise { + const deviceReader = DeviceReaderService.getInstance(); + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + const wallet = await deviceReader.getDeviceFromDatabase(); + if (wallet) { + if (attempt > 0) { + console.log(`✅ Wallet found after ${attempt + 1} attempts`); + } + return wallet; + } + + if (attempt < maxAttempts - 1) { + console.log(`⚠️ Wallet not found, waiting for database synchronization (attempt ${attempt + 1}/${maxAttempts})...`); + await new Promise(resolve => setTimeout(resolve, delayMs)); + } + } + + console.log(`⚠️ Wallet still not found after ${maxAttempts} attempts`); + return null; +} + +/** + * Vérifie tous les prérequis nécessaires pour une page + * @returns Objet avec les résultats des vérifications + */ +export async function checkAllPrerequisites(): Promise<{ + pbkdf2Key: { key: string; mode: SecurityMode } | null; + wallet: any | null; +}> { + const pbkdf2Key = await checkPBKDF2Key(); + const wallet = pbkdf2Key ? await checkWalletWithRetries() : null; + + return { pbkdf2Key, wallet }; +} +