refactor(iframe-controller): standardize import statements, enhance logging, and improve error handling in IframeController service

This commit is contained in:
NicolasCantu 2025-11-28 00:13:51 +01:00
parent 8a87fe38c5
commit 96ee5b03e6

View File

@ -1,9 +1,9 @@
import { MessageType } from '../types/index'; import { MessageType } from "../types/index";
import Services from './service'; import Services from "./service";
import TokenService from './token.service'; import TokenService from "./token.service";
import { cleanSubscriptions } from '../utils/subscription.utils'; import { cleanSubscriptions } from "../utils/subscription.utils";
import { splitPrivateData, isValid32ByteHex } from '../utils/service.utils'; import { splitPrivateData, isValid32ByteHex } from "../utils/service.utils";
import { MerkleProofResult } from '../../pkg/sdk_client'; import { MerkleProofResult } from "../../pkg/sdk_client";
export class IframeController { export class IframeController {
private static isInitialized = false; // <--- VERROU private static isInitialized = false; // <--- VERROU
@ -13,39 +13,57 @@ export class IframeController {
// On ne lance l'écoute que si on est dans une iframe // On ne lance l'écoute que si on est dans une iframe
if (window.self !== window.top) { if (window.self !== window.top) {
console.log('[IframeController] 📡 Mode Iframe détecté. Démarrage des listeners API...'); console.log(
"[IframeController] 📡 Mode Iframe détecté. Démarrage des listeners API..."
);
await IframeController.registerAllListeners(); await IframeController.registerAllListeners();
} else { } else {
console.log("[IframeController] Mode Standalone (pas d'iframe). Listeners API inactifs."); console.log(
"[IframeController] Mode Standalone (pas d'iframe). Listeners API inactifs."
);
} }
} }
private static async registerAllListeners() { private static async registerAllListeners() {
console.log('[Router:API] 🎧 Enregistrement des gestionnaires de messages (postMessage)...'); console.log(
"[Router:API] 🎧 Enregistrement des gestionnaires de messages (postMessage)..."
);
const services = await Services.getInstance(); const services = await Services.getInstance();
const tokenService = await TokenService.getInstance(); const tokenService = await TokenService.getInstance();
/** /**
* Fonction centralisée pour envoyer des réponses d'erreur à la fenêtre parente (l'application A). * Fonction centralisée pour envoyer des réponses d'erreur à la fenêtre parente (l'application A).
*/ */
const errorResponse = (errorMsg: string, origin: string, messageId?: string) => { const errorResponse = (
console.error(`[Router:API] 📤 Envoi Erreur: ${errorMsg} (Origine: ${origin}, MsgID: ${messageId})`); errorMsg: string,
origin: string,
messageId?: string
) => {
console.error(
`[Router:API] 📤 Envoi Erreur: ${errorMsg} (Origine: ${origin}, MsgID: ${messageId})`
);
window.parent.postMessage( window.parent.postMessage(
{ {
type: MessageType.ERROR, type: MessageType.ERROR,
error: errorMsg, error: errorMsg,
messageId, messageId,
}, },
origin, origin
); );
}; };
// Helper pour vérifier le token avant chaque action sensible // Helper pour vérifier le token avant chaque action sensible
const withToken = async (event: MessageEvent, action: () => Promise<void>) => { const withToken = async (
event: MessageEvent,
action: () => Promise<void>
) => {
const { accessToken } = event.data; const { accessToken } = event.data;
// On vérifie si le token est présent ET valide pour l'origine de l'iframe // On vérifie si le token est présent ET valide pour l'origine de l'iframe
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) { if (
throw new Error('Invalid or expired session token'); !accessToken ||
!(await tokenService.validateToken(accessToken, event.origin))
) {
throw new Error("Invalid or expired session token");
} }
// Si tout est bon, on exécute l'action // Si tout est bon, on exécute l'action
await action(); await action();
@ -54,35 +72,53 @@ export class IframeController {
// --- Définitions des gestionnaires (Handlers) --- // --- Définitions des gestionnaires (Handlers) ---
const handleRequestLink = async (event: MessageEvent) => { const handleRequestLink = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.REQUEST_LINK} reçu de ${event.origin}`); console.log(
`[Router:API] 📨 Message ${MessageType.REQUEST_LINK} reçu de ${event.origin}`
);
// 1. Vérifier si l'appareil est DÉJÀ appairé (cas de la 2ème connexion) // 1. Vérifier si l'appareil est DÉJÀ appairé (cas de la 2ème connexion)
const device = await services.getDeviceFromDatabase(); const device = await services.getDeviceFromDatabase();
if (device && device.pairing_process_commitment) { if (device && device.pairing_process_commitment) {
console.log("[Router:API] Appareil déjà appairé. Pas besoin d'attendre home.ts."); console.log(
"[Router:API] Appareil déjà appairé. Pas besoin d'attendre home.ts."
);
// On saute l'attente et on passe directement à la suite. // On saute l'attente et on passe directement à la suite.
} else { } else {
// 2. Cas de la 1ère connexion (appareil non appairé) // 2. Cas de la 1ère connexion (appareil non appairé)
// On doit attendre que home.ts (auto-pairing) ait fini son travail. // On doit attendre que home.ts (auto-pairing) ait fini son travail.
console.log('[Router:API] Appareil non appairé. En attente du feu vert de home.ts...'); await new Promise<void>((resolve, reject) => {
const maxWait = 5000; // 5 sec // Fonction de nettoyage pour éviter les fuites de mémoire
let waited = 0; const cleanup = () => {
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); document.removeEventListener(
"app:pairing-ready",
handler as EventListener
);
clearTimeout(timeoutId);
};
// On attend le drapeau global // Le gestionnaire de l'événement
while (!(window as any).__PAIRING_READY && waited < maxWait) { const handler = (e: CustomEvent) => {
await delay(100); cleanup();
waited += 100; if (e.detail && e.detail.success) {
} resolve();
} else {
reject(new Error(e.detail?.error || "Auto-pairing failed"));
}
};
// 3. Vérifier le résultat de l'attente // Timeout de sécurité (5 secondes)
if ((window as any).__PAIRING_READY === 'error') { const timeoutId = setTimeout(() => {
throw new Error('Auto-pairing failed'); cleanup();
} reject(new Error("Auto-pairing timed out (Event not received)"));
if (!(window as any).__PAIRING_READY) { }, 5000);
throw new Error('Auto-pairing timed out');
} // On écoute l'événement qu'on a créé dans Home.ts
document.addEventListener(
"app:pairing-ready",
handler as EventListener
);
});
console.log(`[Router:API] Feu vert de home.ts reçu !`); console.log(`[Router:API] Feu vert de home.ts reçu !`);
} }
@ -98,50 +134,69 @@ export class IframeController {
refreshToken: tokens.refreshToken, refreshToken: tokens.refreshToken,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
);
console.log(
`[Router:API] ✅ ${MessageType.REQUEST_LINK} accepté et jetons envoyés.`
); );
console.log(`[Router:API] ✅ ${MessageType.REQUEST_LINK} accepté et jetons envoyés.`);
}; };
const handleCreatePairing = async (event: MessageEvent) => { const handleCreatePairing = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.CREATE_PAIRING} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.CREATE_PAIRING} reçu`);
if (services.isPaired()) { if (services.isPaired()) {
throw new Error('Device already paired — ignoring CREATE_PAIRING request'); throw new Error(
"Device already paired — ignoring CREATE_PAIRING request"
);
} }
await withToken(event, async () => { await withToken(event, async () => {
console.log("[Router:API] 🚀 Démarrage du processus d'appairage..."); console.log("[Router:API] 🚀 Démarrage du processus d'appairage...");
const myAddress = services.getDeviceAddress(); const myAddress = services.getDeviceAddress();
console.log('[Router:API] 1/7: Création du processus de pairing...'); console.log("[Router:API] 1/7: Création du processus de pairing...");
const createPairingProcessReturn = await services.createPairingProcess('', [myAddress]); const createPairingProcessReturn = await services.createPairingProcess(
"",
[myAddress]
);
const pairingId = createPairingProcessReturn.updated_process?.process_id; const pairingId =
const stateId = createPairingProcessReturn.updated_process?.current_process?.states[0]?.state_id as string; createPairingProcessReturn.updated_process?.process_id;
const stateId = createPairingProcessReturn.updated_process
?.current_process?.states[0]?.state_id as string;
if (!pairingId || !stateId) { if (!pairingId || !stateId) {
throw new Error('Pairing process creation failed to return valid IDs'); throw new Error(
"Pairing process creation failed to return valid IDs"
);
} }
console.log(`[Router:API] 2/7: Processus ${pairingId} créé.`); console.log(`[Router:API] 2/7: Processus ${pairingId} créé.`);
console.log("[Router:API] 3/7: Enregistrement local de l'appareil..."); console.log("[Router:API] 3/7: Enregistrement local de l'appareil...");
services.pairDevice(pairingId, [myAddress]); services.pairDevice(pairingId, [myAddress]);
console.log('[Router:API] 4/7: Traitement du retour (handleApiReturn)...'); console.log(
"[Router:API] 4/7: Traitement du retour (handleApiReturn)..."
);
await services.handleApiReturn(createPairingProcessReturn); await services.handleApiReturn(createPairingProcessReturn);
console.log('[Router:API] 5/7: Création de la mise à jour PRD...'); console.log("[Router:API] 5/7: Création de la mise à jour PRD...");
const createPrdUpdateReturn = await services.createPrdUpdate(pairingId, stateId); const createPrdUpdateReturn = await services.createPrdUpdate(
pairingId,
stateId
);
await services.handleApiReturn(createPrdUpdateReturn); await services.handleApiReturn(createPrdUpdateReturn);
console.log('[Router:API] 6/7: Approbation du changement...'); console.log("[Router:API] 6/7: Approbation du changement...");
const approveChangeReturn = await services.approveChange(pairingId, stateId); const approveChangeReturn = await services.approveChange(
pairingId,
stateId
);
await services.handleApiReturn(approveChangeReturn); await services.handleApiReturn(approveChangeReturn);
console.log('[Router:API] 7/7: Confirmation finale du pairing...'); console.log("[Router:API] 7/7: Confirmation finale du pairing...");
// await services.confirmPairing(); // await services.confirmPairing();
console.log('[Router:API] 🎉 Appairage terminé avec succès !'); console.log("[Router:API] 🎉 Appairage terminé avec succès !");
const successMsg = { const successMsg = {
type: MessageType.PAIRING_CREATED, type: MessageType.PAIRING_CREATED,
@ -153,8 +208,10 @@ export class IframeController {
}; };
const handleGetMyProcesses = async (event: MessageEvent) => { const handleGetMyProcesses = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.GET_MY_PROCESSES} reçu`); console.log(
if (!services.isPaired()) throw new Error('Device not paired'); `[Router:API] 📨 Message ${MessageType.GET_MY_PROCESSES} reçu`
);
if (!services.isPaired()) throw new Error("Device not paired");
await withToken(event, async () => { await withToken(event, async () => {
const myProcesses = await services.getMyProcesses(); const myProcesses = await services.getMyProcesses();
@ -165,14 +222,14 @@ export class IframeController {
myProcesses, myProcesses,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleGetProcesses = async (event: MessageEvent) => { const handleGetProcesses = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.GET_PROCESSES} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.GET_PROCESSES} reçu`);
if (!services.isPaired()) throw new Error('Device not paired'); if (!services.isPaired()) throw new Error("Device not paired");
await withToken(event, async () => { await withToken(event, async () => {
const processes = await services.getProcesses(); const processes = await services.getProcesses();
@ -183,14 +240,14 @@ export class IframeController {
processes, processes,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleDecryptState = async (event: MessageEvent) => { const handleDecryptState = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.RETRIEVE_DATA} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.RETRIEVE_DATA} reçu`);
if (!services.isPaired()) throw new Error('Device not paired'); if (!services.isPaired()) throw new Error("Device not paired");
const { processId, stateId } = event.data; const { processId, stateId } = event.data;
@ -199,22 +256,36 @@ export class IframeController {
if (!process) throw new Error("Can't find process"); if (!process) throw new Error("Can't find process");
const state = services.getStateFromId(process, stateId); const state = services.getStateFromId(process, stateId);
if (!state) throw new Error(`Unknown state ${stateId} for process ${processId}`); if (!state)
throw new Error(`Unknown state ${stateId} for process ${processId}`);
console.log(`[Router:API] 🔐 Démarrage du déchiffrement pour ${processId}`); console.log(
`[Router:API] 🔐 Démarrage du déchiffrement pour ${processId}`
);
await services.ensureConnections(process, stateId); await services.ensureConnections(process, stateId);
const res: Record<string, any> = {}; const res: Record<string, any> = {};
for (const attribute of Object.keys(state.pcd_commitment)) { for (const attribute of Object.keys(state.pcd_commitment)) {
if (attribute === 'roles' || (state.public_data && state.public_data[attribute])) { if (
attribute === "roles" ||
(state.public_data && state.public_data[attribute])
) {
continue; continue;
} }
const decryptedAttribute = await services.decryptAttribute(processId, state, attribute); const decryptedAttribute = await services.decryptAttribute(
processId,
state,
attribute
);
if (decryptedAttribute) { if (decryptedAttribute) {
res[attribute] = decryptedAttribute; res[attribute] = decryptedAttribute;
} }
} }
console.log(`[Router:API] ✅ Déchiffrement terminé pour ${processId}. ${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( window.parent.postMessage(
{ {
@ -222,7 +293,7 @@ export class IframeController {
data: res, data: res,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
@ -232,10 +303,13 @@ export class IframeController {
const accessToken = event.data.accessToken; const accessToken = event.data.accessToken;
const refreshToken = event.data.refreshToken; const refreshToken = event.data.refreshToken;
if (!accessToken || !refreshToken) { if (!accessToken || !refreshToken) {
throw new Error('Missing access, refresh token or both'); throw new Error("Missing access, refresh token or both");
} }
const isValid = await tokenService.validateToken(accessToken, event.origin); const isValid = await tokenService.validateToken(
accessToken,
event.origin
);
console.log(`[Router:API] 🔑 Validation Jeton: ${isValid}`); console.log(`[Router:API] 🔑 Validation Jeton: ${isValid}`);
window.parent.postMessage( window.parent.postMessage(
{ {
@ -245,17 +319,21 @@ export class IframeController {
isValid: isValid, isValid: isValid,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}; };
const handleRenewToken = async (event: MessageEvent) => { const handleRenewToken = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.RENEW_TOKEN} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.RENEW_TOKEN} reçu`);
const refreshToken = event.data.refreshToken; const refreshToken = event.data.refreshToken;
if (!refreshToken) throw new Error('No refresh token provided'); if (!refreshToken) throw new Error("No refresh token provided");
const newAccessToken = await tokenService.refreshAccessToken(refreshToken, event.origin); const newAccessToken = await tokenService.refreshAccessToken(
if (!newAccessToken) throw new Error('Failed to refresh token (invalid refresh token)'); refreshToken,
event.origin
);
if (!newAccessToken)
throw new Error("Failed to refresh token (invalid refresh token)");
console.log(`[Router:API] 🔑 Jeton d'accès renouvelé.`); console.log(`[Router:API] 🔑 Jeton d'accès renouvelé.`);
window.parent.postMessage( window.parent.postMessage(
@ -265,7 +343,7 @@ export class IframeController {
refreshToken: refreshToken, refreshToken: refreshToken,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}; };
@ -285,19 +363,29 @@ export class IframeController {
if (device && device.pairing_process_commitment) { if (device && device.pairing_process_commitment) {
// SUCCÈS ! L'ID est dans la BDD // SUCCÈS ! L'ID est dans la BDD
pairingId = device.pairing_process_commitment; pairingId = device.pairing_process_commitment;
console.log(`[Router:API] GET_PAIRING_ID: ID trouvé en BDD (tentative ${i + 1}/${maxRetries})`); console.log(
`[Router:API] GET_PAIRING_ID: ID trouvé en BDD (tentative ${
i + 1
}/${maxRetries})`
);
break; // On sort de la boucle break; // On sort de la boucle
} }
// Si non trouvé, on patiente // Si non trouvé, on patiente
console.warn(`[Router:API] GET_PAIRING_ID: Non trouvé en BDD, nouvelle tentative... (${i + 1}/${maxRetries})`); console.warn(
`[Router:API] GET_PAIRING_ID: Non trouvé en BDD, nouvelle tentative... (${
i + 1
}/${maxRetries})`
);
await new Promise((resolve) => setTimeout(resolve, retryDelay)); await new Promise((resolve) => setTimeout(resolve, retryDelay));
} }
// Si la boucle se termine sans succès // Si la boucle se termine sans succès
if (!pairingId) { if (!pairingId) {
console.error(`[Router:API] GET_PAIRING_ID: Échec final, non trouvé en BDD après ${maxRetries} tentatives.`); console.error(
throw new Error('Device not paired'); `[Router:API] GET_PAIRING_ID: Échec final, non trouvé en BDD après ${maxRetries} tentatives.`
);
throw new Error("Device not paired");
} }
await withToken(event, async () => { await withToken(event, async () => {
@ -307,31 +395,42 @@ export class IframeController {
userPairingId: pairingId, userPairingId: pairingId,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleCreateProcess = async (event: MessageEvent) => { const handleCreateProcess = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.CREATE_PROCESS} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.CREATE_PROCESS} reçu`);
if (!services.isPaired()) throw new Error('Device not paired'); if (!services.isPaired()) throw new Error("Device not paired");
const { processData, privateFields, roles } = event.data; const { processData, privateFields, roles } = event.data;
await withToken(event, async () => { await withToken(event, async () => {
console.log('[Router:API] 🚀 Démarrage de la création de processus standard...'); console.log(
const { privateData, publicData } = splitPrivateData(processData, privateFields); "[Router:API] 🚀 Démarrage de la création de processus standard..."
);
const { privateData, publicData } = splitPrivateData(
processData,
privateFields
);
console.log('[Router:API] 1/2: Création du processus...'); console.log("[Router:API] 1/2: Création du processus...");
const createProcessReturn = await services.createProcess(privateData, publicData, roles); const createProcessReturn = await services.createProcess(
privateData,
publicData,
roles
);
if (!createProcessReturn.updated_process) { if (!createProcessReturn.updated_process) {
throw new Error('Empty updated_process in createProcessReturn'); throw new Error("Empty updated_process in createProcessReturn");
} }
const processId = createProcessReturn.updated_process.process_id; const processId = createProcessReturn.updated_process.process_id;
const process = createProcessReturn.updated_process.current_process; const process = createProcessReturn.updated_process.current_process;
const stateId = process.states[0].state_id; const stateId = process.states[0].state_id;
console.log(`[Router:API] 2/2: Processus ${processId} créé. Traitement...`); console.log(
`[Router:API] 2/2: Processus ${processId} créé. Traitement...`
);
await services.handleApiReturn(createProcessReturn); await services.handleApiReturn(createProcessReturn);
console.log(`[Router:API] 🎉 Processus ${processId} créé.`); console.log(`[Router:API] 🎉 Processus ${processId} créé.`);
@ -348,19 +447,19 @@ export class IframeController {
processCreated: res, processCreated: res,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleNotifyUpdate = async (event: MessageEvent) => { const handleNotifyUpdate = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.NOTIFY_UPDATE} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.NOTIFY_UPDATE} reçu`);
if (!services.isPaired()) throw new Error('Device not paired'); if (!services.isPaired()) throw new Error("Device not paired");
const { processId, stateId } = event.data; const { processId, stateId } = event.data;
await withToken(event, async () => { await withToken(event, async () => {
if (!isValid32ByteHex(stateId)) throw new Error('Invalid state id'); if (!isValid32ByteHex(stateId)) throw new Error("Invalid state id");
const res = await services.createPrdUpdate(processId, stateId); const res = await services.createPrdUpdate(processId, stateId);
await services.handleApiReturn(res); await services.handleApiReturn(res);
@ -370,14 +469,14 @@ export class IframeController {
type: MessageType.UPDATE_NOTIFIED, type: MessageType.UPDATE_NOTIFIED,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleValidateState = async (event: MessageEvent) => { const handleValidateState = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.VALIDATE_STATE} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.VALIDATE_STATE} reçu`);
if (!services.isPaired()) throw new Error('Device not paired'); if (!services.isPaired()) throw new Error("Device not paired");
const { processId, stateId } = event.data; const { processId, stateId } = event.data;
@ -391,22 +490,29 @@ export class IframeController {
validatedProcess: res.updated_process, validatedProcess: res.updated_process,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleUpdateProcess = async (event: MessageEvent) => { const handleUpdateProcess = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.UPDATE_PROCESS} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.UPDATE_PROCESS} reçu`);
if (!services.isPaired()) throw new Error('Device not paired'); if (!services.isPaired()) throw new Error("Device not paired");
const { processId, newData, privateFields, roles } = event.data; const { processId, newData, privateFields, roles } = event.data;
await withToken(event, async () => { await withToken(event, async () => {
console.log(`[Router:API] 🔄 Transfert de la mise à jour de ${processId} au service...`); console.log(
`[Router:API] 🔄 Transfert de la mise à jour de ${processId} au service...`
);
// Le service gère maintenant tout : récupération, réparation d'état, et mise à jour. // 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 res = await services.updateProcess(
processId,
newData,
privateFields,
roles
);
// Nous appelons handleApiReturn ici, comme avant. // Nous appelons handleApiReturn ici, comme avant.
await services.handleApiReturn(res); await services.handleApiReturn(res);
@ -418,14 +524,16 @@ export class IframeController {
updatedProcess: res.updated_process, // res vient directement de l'appel service updatedProcess: res.updated_process, // res vient directement de l'appel service
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleDecodePublicData = async (event: MessageEvent) => { const handleDecodePublicData = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.DECODE_PUBLIC_DATA} reçu`); console.log(
if (!services.isPaired()) throw new Error('Device not paired'); `[Router:API] 📨 Message ${MessageType.DECODE_PUBLIC_DATA} reçu`
);
if (!services.isPaired()) throw new Error("Device not paired");
const { encodedData } = event.data; const { encodedData } = event.data;
@ -437,7 +545,7 @@ export class IframeController {
decodedData, decodedData,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
@ -454,30 +562,37 @@ export class IframeController {
hash, hash,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleGetMerkleProof = async (event: MessageEvent) => { const handleGetMerkleProof = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.GET_MERKLE_PROOF} reçu`); console.log(
`[Router:API] 📨 Message ${MessageType.GET_MERKLE_PROOF} reçu`
);
const { processState, attributeName } = event.data; const { processState, attributeName } = event.data;
await withToken(event, async () => { await withToken(event, async () => {
const proof = services.getMerkleProofForFile(processState, attributeName); const proof = services.getMerkleProofForFile(
processState,
attributeName
);
window.parent.postMessage( window.parent.postMessage(
{ {
type: MessageType.MERKLE_PROOF_RETRIEVED, type: MessageType.MERKLE_PROOF_RETRIEVED,
proof, proof,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
const handleValidateMerkleProof = async (event: MessageEvent) => { const handleValidateMerkleProof = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.VALIDATE_MERKLE_PROOF} reçu`); console.log(
`[Router:API] 📨 Message ${MessageType.VALIDATE_MERKLE_PROOF} reçu`
);
const { merkleProof, documentHash } = event.data; const { merkleProof, documentHash } = event.data;
await withToken(event, async () => { await withToken(event, async () => {
@ -485,25 +600,28 @@ export class IframeController {
try { try {
parsedMerkleProof = JSON.parse(merkleProof); parsedMerkleProof = JSON.parse(merkleProof);
} catch (e) { } catch (e) {
throw new Error('Provided merkleProof is not a valid json object'); throw new Error("Provided merkleProof is not a valid json object");
} }
const res = services.validateMerkleProof(parsedMerkleProof, documentHash); const res = services.validateMerkleProof(
parsedMerkleProof,
documentHash
);
window.parent.postMessage( window.parent.postMessage(
{ {
type: MessageType.MERKLE_PROOF_VALIDATED, type: MessageType.MERKLE_PROOF_VALIDATED,
isValid: res, isValid: res,
messageId: event.data.messageId, messageId: event.data.messageId,
}, },
event.origin, event.origin
); );
}); });
}; };
// --- Le "Switchyard" : il reçoit tous les messages et les dispatche --- // --- Le "Switchyard" : il reçoit tous les messages et les dispatche ---
window.removeEventListener('message', handleMessage); window.removeEventListener("message", handleMessage);
window.addEventListener('message', handleMessage); window.addEventListener("message", handleMessage);
async function handleMessage(event: MessageEvent) { async function handleMessage(event: MessageEvent) {
try { try {
@ -557,7 +675,7 @@ export class IframeController {
await handleValidateMerkleProof(event); await handleValidateMerkleProof(event);
break; break;
default: default:
console.warn('[Router:API] ⚠️ Message non géré reçu:', event.data); console.warn("[Router:API] ⚠️ Message non géré reçu:", event.data);
} }
} catch (error: any) { } catch (error: any) {
const errorMsg = `[Router:API] 💥 Erreur de haut niveau: ${error}`; const errorMsg = `[Router:API] 💥 Erreur de haut niveau: ${error}`;
@ -569,9 +687,10 @@ export class IframeController {
{ {
type: MessageType.LISTENING, type: MessageType.LISTENING,
}, },
'*', "*"
);
console.log(
"[Router:API] ✅ Tous les listeners sont actifs. Envoi du message LISTENING au parent."
); );
console.log('[Router:API] ✅ Tous les listeners sont actifs. Envoi du message LISTENING au parent.');
} }
} }