Added withToken func to remove the duplicated code

This commit is contained in:
NicolasCantu 2025-11-25 09:57:57 +01:00
parent 740a29688d
commit 8512b90d36

View File

@ -6,7 +6,11 @@ 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
static async init() { static async init() {
if (this.isInitialized) return; // On sort si déjà lancé
// 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...');
@ -36,6 +40,17 @@ export class IframeController {
); );
}; };
// Helper pour vérifier le token avant chaque action sensible
const withToken = async (event: MessageEvent, action: () => Promise<void>) => {
const { accessToken } = event.data;
// 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))) {
throw new Error('Invalid or expired session token');
}
// Si tout est bon, on exécute l'action
await action();
};
// --- Définitions des gestionnaires (Handlers) --- // --- Définitions des gestionnaires (Handlers) ---
const handleRequestLink = async (event: MessageEvent) => { const handleRequestLink = async (event: MessageEvent) => {
@ -95,11 +110,7 @@ export class IframeController {
throw new Error('Device already paired — ignoring CREATE_PAIRING request'); throw new Error('Device already paired — ignoring CREATE_PAIRING request');
} }
const { accessToken } = event.data; await withToken(event, async () => {
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
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();
@ -138,17 +149,14 @@ export class IframeController {
messageId: event.data.messageId, messageId: event.data.messageId,
}; };
window.parent.postMessage(successMsg, event.origin); window.parent.postMessage(successMsg, event.origin);
});
}; };
const handleGetMyProcesses = async (event: MessageEvent) => { const handleGetMyProcesses = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.GET_MY_PROCESSES} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.GET_MY_PROCESSES} reçu`);
if (!services.isPaired()) throw new Error('Device not paired'); if (!services.isPaired()) throw new Error('Device not paired');
const { accessToken } = event.data; await withToken(event, async () => {
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
const myProcesses = await services.getMyProcesses(); const myProcesses = await services.getMyProcesses();
window.parent.postMessage( window.parent.postMessage(
@ -159,17 +167,14 @@ export class IframeController {
}, },
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');
const { accessToken } = event.data; await withToken(event, async () => {
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
const processes = await services.getProcesses(); const processes = await services.getProcesses();
window.parent.postMessage( window.parent.postMessage(
@ -180,17 +185,16 @@ export class IframeController {
}, },
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, accessToken } = event.data; const { processId, stateId } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
await withToken(event, async () => {
const process = await services.getProcess(processId); const process = await services.getProcess(processId);
if (!process) throw new Error("Can't find process"); if (!process) throw new Error("Can't find process");
@ -220,6 +224,7 @@ export class IframeController {
}, },
event.origin, event.origin,
); );
});
}; };
const handleValidateToken = async (event: MessageEvent) => { const handleValidateToken = async (event: MessageEvent) => {
@ -295,11 +300,7 @@ export class IframeController {
throw new Error('Device not paired'); throw new Error('Device not paired');
} }
const { accessToken } = event.data; await withToken(event, async () => {
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
window.parent.postMessage( window.parent.postMessage(
{ {
type: MessageType.GET_PAIRING_ID, type: MessageType.GET_PAIRING_ID,
@ -308,17 +309,16 @@ export class IframeController {
}, },
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, accessToken } = event.data; const { processData, privateFields, roles } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
await withToken(event, async () => {
console.log('[Router:API] 🚀 Démarrage de la création de processus standard...'); console.log('[Router:API] 🚀 Démarrage de la création de processus standard...');
const { privateData, publicData } = splitPrivateData(processData, privateFields); const { privateData, publicData } = splitPrivateData(processData, privateFields);
@ -350,16 +350,16 @@ export class IframeController {
}, },
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, accessToken } = event.data; const { processId, stateId } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token'); 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);
@ -372,17 +372,16 @@ export class IframeController {
}, },
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, accessToken } = event.data; const { processId, stateId } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
await withToken(event, async () => {
const res = await services.approveChange(processId, stateId); const res = await services.approveChange(processId, stateId);
await services.handleApiReturn(res); await services.handleApiReturn(res);
@ -394,17 +393,16 @@ export class IframeController {
}, },
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, accessToken } = event.data; const { processId, newData, privateFields, roles } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
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.
@ -422,17 +420,16 @@ export class IframeController {
}, },
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(`[Router:API] 📨 Message ${MessageType.DECODE_PUBLIC_DATA} reçu`);
if (!services.isPaired()) throw new Error('Device not paired'); if (!services.isPaired()) throw new Error('Device not paired');
const { accessToken, encodedData } = event.data; const { encodedData } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
await withToken(event, async () => {
const decodedData = services.decodeValue(encodedData); const decodedData = services.decodeValue(encodedData);
window.parent.postMessage( window.parent.postMessage(
{ {
@ -442,15 +439,14 @@ export class IframeController {
}, },
event.origin, event.origin,
); );
});
}; };
const handleHashValue = async (event: MessageEvent) => { const handleHashValue = async (event: MessageEvent) => {
console.log(`[Router:API] 📨 Message ${MessageType.HASH_VALUE} reçu`); console.log(`[Router:API] 📨 Message ${MessageType.HASH_VALUE} reçu`);
const { accessToken, commitedIn, label, fileBlob } = event.data; const { commitedIn, label, fileBlob } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
await withToken(event, async () => {
const hash = services.getHashForFile(commitedIn, label, fileBlob); const hash = services.getHashForFile(commitedIn, label, fileBlob);
window.parent.postMessage( window.parent.postMessage(
{ {
@ -460,15 +456,14 @@ export class IframeController {
}, },
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 { accessToken, processState, attributeName } = event.data; const { processState, attributeName } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
await withToken(event, async () => {
const proof = services.getMerkleProofForFile(processState, attributeName); const proof = services.getMerkleProofForFile(processState, attributeName);
window.parent.postMessage( window.parent.postMessage(
{ {
@ -478,15 +473,14 @@ export class IframeController {
}, },
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 { accessToken, merkleProof, documentHash } = event.data; const { merkleProof, documentHash } = event.data;
if (!accessToken || !(await tokenService.validateToken(accessToken, event.origin))) {
throw new Error('Invalid or expired session token');
}
await withToken(event, async () => {
let parsedMerkleProof: MerkleProofResult; let parsedMerkleProof: MerkleProofResult;
try { try {
parsedMerkleProof = JSON.parse(merkleProof); parsedMerkleProof = JSON.parse(merkleProof);
@ -503,6 +497,7 @@ export class IframeController {
}, },
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 ---