diff --git a/src/router.ts b/src/router.ts index ab94907..19edfd8 100755 --- a/src/router.ts +++ b/src/router.ts @@ -443,7 +443,7 @@ export async function registerAllListeners() { const state = services.getStateFromId(process, stateId); if (!state) throw new Error(`Unknown state ${stateId} for process ${processId}`); - console.log(`[Router:API] 🔐 Démarrage du déchiffrement pour ${processId}:${stateId}`); + console.log(`[Router:API] 🔐 Démarrage du déchiffrement pour ${processId}`); await services.ensureConnections(process, stateId); const res: Record = {}; @@ -456,7 +456,7 @@ export async function registerAllListeners() { res[attribute] = decryptedAttribute; } } - console.log(`[Router:API] ✅ Déchiffrement terminé pour ${processId}:${stateId}. ${Object.keys(res).length} attribut(s) déchiffré(s).`); + console.log(`[Router:API] ✅ Déchiffrement terminé pour ${processId}. ${Object.keys(res).length} attribut(s) déchiffré(s).`); window.parent.postMessage( { @@ -517,7 +517,7 @@ export async function registerAllListeners() { const retryDelay = 300; let pairingId: string | null = null; - // Boucle de polling + // Boucle de polling for (let i = 0; i < maxRetries; i++) { // On lit DIRECTEMENT la BDD (la "source de vérité") const device = await services.getDeviceFromDatabase(); @@ -651,69 +651,19 @@ export async function registerAllListeners() { throw new Error('Invalid or expired session token'); } - const process = await services.getProcess(processId); - if (!process) throw new Error('Process not found'); + console.log(`[Router:API] 🔄 Transfert de la mise à jour de ${processId} au service...`); - // --- Logique complexe de gestion d'état --- - // (Cette logique est très dense et pourrait être déplacée dans le service) - console.log(`[Router:API] 🔄 Calcul de la diff pour la mise à jour de ${processId}...`); - let lastState = services.getLastCommitedState(process); - if (!lastState) { - console.warn(`[Router:API] ⚠️ Processus ${processId} n'a pas d'état "commited". Tentative d'auto-approbation du 1er état...`); - const firstState = process.states[0]; - const roles = firstState.roles; - if (services.rolesContainsUs(roles)) { - const approveChangeRes = await services.approveChange(processId, firstState.state_id); - await services.handleApiReturn(approveChangeRes); - const prdUpdateRes = await services.createPrdUpdate(processId, firstState.state_id); - await services.handleApiReturn(prdUpdateRes); - } else { - if (firstState.validation_tokens.length > 0) { - const res = await services.createPrdUpdate(processId, firstState.state_id); - await services.handleApiReturn(res); - } - } - await new Promise((resolve) => setTimeout(resolve, 2000)); // Attente arbitraire - lastState = services.getLastCommitedState(process); - if (!lastState) { - throw new Error("Process doesn't have a commited state yet"); - } - } - const lastStateIndex = services.getLastCommitedStateIndex(process); - if (lastStateIndex === null) throw new Error("Process doesn't have a commited state yet"); + // Le service gère maintenant tout : récupération, réparation d'état, et mise à jour. + const res = await services.updateProcess(processId, newData, privateFields, roles); - const privateData: Record = {}; - const publicData: Record = {}; - - for (const field of Object.keys(newData)) { - if (lastState.public_data[field]) { - publicData[field] = newData[field]; - continue; - } - if (privateFields.includes(field)) { - privateData[field] = newData[field]; - continue; - } - for (let i = lastStateIndex; i >= 0; i--) { - const state = process.states[i]; - if (state.pcd_commitment[field]) { - privateData[field] = newData[field]; - break; - } else { - continue; - } - } - if (privateData[field]) continue; - publicData[field] = newData[field]; - } - console.log(`[Router:API] 🔄 Envoi de la mise à jour à services.updateProcess...`); - const res = await services.updateProcess(process, privateData, publicData, roles); + // Nous appelons handleApiReturn ici, comme avant. await services.handleApiReturn(res); + // --- FIN DE LA MODIFICATION --- window.parent.postMessage( { type: MessageType.PROCESS_UPDATED, - updatedProcess: res.updated_process, + updatedProcess: res.updated_process, // res vient directement de l'appel service messageId: event.data.messageId, }, event.origin, diff --git a/src/services/service.ts b/src/services/service.ts index a79a35d..f0c5171 100755 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -659,13 +659,106 @@ export default class Services { return { encodedPrivateData, encodedPublicData }; } - public async updateProcess(process: Process, privateData: Record, publicData: Record, roles: Record | null): Promise { - // If roles is null, we just take the last commited state roles - if (!roles) { - roles = this.getRoles(process); - } else { - console.log('[Services:updateProcess] ℹ️ Utilisation de nouveaux rôles fournis:', JSON.stringify(roles)); + /** + * Met à jour un processus. + * Gère la logique complexe de recherche du dernier état "commited" + * et tente une auto-approbation si nécessaire. + */ + public async updateProcess( + processId: string, // Changement : on reçoit l'ID, pas l'objet Process + newData: Record, // Changement : on reçoit les nouvelles données + privateFields: string[], // Changement : on reçoit les champs privés + roles: Record | null, + ): Promise { + // 1. Récupérer le processus + const process = await this.getProcess(processId); + if (!process) { + throw new Error(`[Services:updateProcess] Processus ${processId} non trouvé`); } + + // --- DEBUT DE LA LOGIQUE DÉPLACÉE DU ROUTEUR --- + + // 2. Trouver le dernier état et le "réparer" si nécessaire + let lastState = this.getLastCommitedState(process); + let currentProcess = process; // Garde une trace du processus à jour + + if (!lastState) { + console.warn(`[Services:updateProcess] ⚠️ Processus ${processId} n'a pas d'état "commited". Tentative d'auto-approbation...`); + const firstState = process.states[0]; + + if (this.rolesContainsUs(firstState.roles)) { + // ON REMPLACE LE setTimeout PAR UN VRAI AWAIT + console.log(`[Services:updateProcess] Auto-approbation de l'état ${firstState.state_id}...`); + const approveChangeRes = await this.approveChange(processId, firstState.state_id); + await this.handleApiReturn(approveChangeRes); // On attend que la BDD soit à jour + + console.log(`[Services:updateProcess] Création de la PRD update pour l'état ${firstState.state_id}...`); + const prdUpdateRes = await this.createPrdUpdate(processId, firstState.state_id); + await this.handleApiReturn(prdUpdateRes); // On attend à nouveau + } else { + if (firstState.validation_tokens.length > 0) { + console.log(`[Services:updateProcess] Création de la PRD update (sans approbation) pour l'état ${firstState.state_id}...`); + const res = await this.createPrdUpdate(processId, firstState.state_id); + await this.handleApiReturn(res); + } + } + + // 3. Re-synchroniser l'état après nos actions + console.log(`[Services:updateProcess] Re-vérification de l'état "commited" après auto-approbation...`); + const updatedProcess = await this.getProcess(processId); // On recharge depuis la BDD + if (!updatedProcess) throw new Error('Le processus a disparu après la tentative de réparation'); + + currentProcess = updatedProcess; // On met à jour notre référence + lastState = this.getLastCommitedState(currentProcess); + + if (!lastState) { + // Si ça échoue toujours, on abandonne + throw new Error("Le processus n'a toujours pas d'état 'commited' après la tentative de réparation."); + } + console.log(`[Services:updateProcess] ✅ État "commited" ${lastState.state_id} trouvé.`); + } + + const lastStateIndex = this.getLastCommitedStateIndex(currentProcess); + if (lastStateIndex === null) { + // Sécurité, bien que logiquement couvert par le bloc ci-dessus + throw new Error("Impossible de trouver l'index du dernier état 'commited'."); + } + + // 4. Calculer les diffs (logique de séparation privée/publique) + const privateData: Record = {}; + const publicData: Record = {}; + + for (const field of Object.keys(newData)) { + if (lastState.public_data[field]) { + publicData[field] = newData[field]; + continue; + } + if (privateFields.includes(field)) { + privateData[field] = newData[field]; + continue; + } + // Logique de recherche dans l'historique + for (let i = lastStateIndex; i >= 0; i--) { + const state = currentProcess.states[i]; + if (state.pcd_commitment[field]) { + privateData[field] = newData[field]; + break; + } + } + if (privateData[field]) continue; + + // Par défaut, c'est public + publicData[field] = newData[field]; + } + + // --- FIN DE LA LOGIQUE DÉPLACÉE DU ROUTEUR --- + + // 5. Exécuter la mise à jour + if (!roles) { + roles = this.getRoles(currentProcess); // Important : utiliser currentProcess + } + + console.log('[Services:updateProcess] ℹ️ Préparation des données binaires et JSON...'); const privateSplitData = this.splitData(privateData); const publicSplitData = this.splitData(publicData); const encodedPrivateData = { @@ -676,10 +769,20 @@ export default class Services { ...this.sdkClient.encode_json(publicSplitData.jsonCompatibleData), ...this.sdkClient.encode_binary(publicSplitData.binaryData), }; + try { - const result = this.sdkClient.update_process(process, encodedPrivateData, roles, encodedPublicData, this.getAllMembers()); + console.log('[Services:updateProcess] 🚀 Appel de sdkClient.update_process...'); + const result = this.sdkClient.update_process( + currentProcess, // Utiliser le processus potentiellement mis à jour + encodedPrivateData, + roles, + encodedPublicData, + this.getAllMembers(), + ); + if (result.updated_process) { - console.log(`[Services:updateProcess] ✅ Processus mis à jour. Vérification des connexions...`, process); + console.log(`[Services:updateProcess] ✅ Processus mis à jour. Vérification des connexions...`); + // On s'assure qu'on est connecté aux membres du nouvel état await this.ensureConnections(result.updated_process.current_process); return result; } else {