Replace handleSource by registeringAllListeners
This commit is contained in:
parent
824a0b88f6
commit
eca4d4de85
@ -1,2 +1,4 @@
|
|||||||
export { default as Services } from './services/service';
|
export { default as Services } from './services/service';
|
||||||
export { default as Database } from './services/database.service';
|
export { default as Database } from './services/database.service';
|
||||||
|
export { MessageType } from './models/process.model';
|
||||||
|
export type { ProfileData, ProfileMessage } from './models/process.model';
|
||||||
|
@ -21,3 +21,77 @@ export interface INotification {
|
|||||||
sendToNotificationPage?: boolean;
|
sendToNotificationPage?: boolean;
|
||||||
path?: string;
|
path?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum MessageType {
|
||||||
|
LISTENING = 'LISTENING',
|
||||||
|
REQUEST_LINK = 'REQUEST_LINK',
|
||||||
|
LINK_ACCEPTED = 'LINK_ACCEPTED',
|
||||||
|
CREATE_PROFILE = 'CREATE_PROFILE',
|
||||||
|
PROFILE_CREATED = 'PROFILE_CREATED',
|
||||||
|
CREATE_FOLDER = 'CREATE_FOLDER',
|
||||||
|
FOLDER_CREATED = 'FOLDER_CREATED',
|
||||||
|
RETRIEVE_DATA = 'RETRIEVE_DATA',
|
||||||
|
DATA_RETRIEVED = 'DATA_RETRIEVED',
|
||||||
|
ERROR = 'ERROR',
|
||||||
|
RENEW_TOKEN = 'RENEW_TOKEN',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProfileData {
|
||||||
|
name: string;
|
||||||
|
surname: string;
|
||||||
|
email: string;
|
||||||
|
phone: string;
|
||||||
|
address: string;
|
||||||
|
postalCode: string;
|
||||||
|
city: string;
|
||||||
|
country: string;
|
||||||
|
idDocument?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProfileMessage {
|
||||||
|
type: MessageType.CREATE_PROFILE;
|
||||||
|
data: ProfileData;
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FolderData {
|
||||||
|
folderNumber: string;
|
||||||
|
name: string;
|
||||||
|
deedType: string;
|
||||||
|
description: string;
|
||||||
|
archived_description: string;
|
||||||
|
status: string;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
customers: string[];
|
||||||
|
documents: string[];
|
||||||
|
motes: string[];
|
||||||
|
stakeholders: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FolderMessage {
|
||||||
|
type: MessageType.CREATE_FOLDER;
|
||||||
|
data: FolderData;
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RetrieveMessage {
|
||||||
|
type: MessageType.RETRIEVE_DATA;
|
||||||
|
processId: string,
|
||||||
|
stateId: string,
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DecryptedDataMessage {
|
||||||
|
type: MessageType.DATA_RETRIEVED;
|
||||||
|
data: string,
|
||||||
|
token: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TokenData {
|
||||||
|
token: string;
|
||||||
|
origin: string;
|
||||||
|
expiration: number;
|
||||||
|
createdAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { addSubscription } from '../../utils/subscription.utils';
|
|||||||
import { displayEmojis, generateQRCode, generateCreateBtn, addressToEmoji} from '../../utils/sp-address.utils';
|
import { displayEmojis, generateQRCode, generateCreateBtn, addressToEmoji} from '../../utils/sp-address.utils';
|
||||||
import { getCorrectDOM } from '../../utils/html.utils';
|
import { getCorrectDOM } from '../../utils/html.utils';
|
||||||
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
|
import QrScannerComponent from '../../components/qrcode-scanner/qrcode-scanner-component';
|
||||||
import { navigate, handleSource } from '../../router';
|
import { navigate, registerAllListeners } from '../../router';
|
||||||
|
|
||||||
export { QrScannerComponent };
|
export { QrScannerComponent };
|
||||||
export async function initHomePage(): Promise<void> {
|
export async function initHomePage(): Promise<void> {
|
||||||
@ -29,17 +29,7 @@ export async function initHomePage(): Promise<void> {
|
|||||||
// Add this line to populate the select when the page loads
|
// Add this line to populate the select when the page loads
|
||||||
await populateMemberSelect();
|
await populateMemberSelect();
|
||||||
|
|
||||||
const endpoint = window.location.pathname;
|
await registerAllListeners();
|
||||||
console.log('endpoint', endpoint);
|
|
||||||
|
|
||||||
if (endpoint && endpoint !== '/') {
|
|
||||||
try {
|
|
||||||
await handleSource(endpoint);
|
|
||||||
console.log('handleSource', endpoint);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error handling endpoint:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//// Modal
|
//// Modal
|
||||||
|
358
src/router.ts
358
src/router.ts
@ -3,11 +3,12 @@ import { initHeader } from '../src/components/header/header';
|
|||||||
/*import { initChat } from '../src/pages/chat/chat';*/
|
/*import { initChat } from '../src/pages/chat/chat';*/
|
||||||
import Database from './services/database.service';
|
import Database from './services/database.service';
|
||||||
import Services from './services/service';
|
import Services from './services/service';
|
||||||
|
import TokenService from './services/token';
|
||||||
import { cleanSubscriptions } from './utils/subscription.utils';
|
import { cleanSubscriptions } from './utils/subscription.utils';
|
||||||
import { LoginComponent } from './pages/home/home-component';
|
import { LoginComponent } from './pages/home/home-component';
|
||||||
import { prepareAndSendPairingTx } from './utils/sp-address.utils';
|
import { prepareAndSendPairingTx } from './utils/sp-address.utils';
|
||||||
import ModalService from './services/modal.service';
|
import ModalService from './services/modal.service';
|
||||||
export { Services };
|
import { MessageType, ProfileData, FolderData } from './models/process.model';
|
||||||
const routes: { [key: string]: string } = {
|
const routes: { [key: string]: string } = {
|
||||||
home: '/src/pages/home/home.html',
|
home: '/src/pages/home/home.html',
|
||||||
process: '/src/pages/process/process.html',
|
process: '/src/pages/process/process.html',
|
||||||
@ -147,14 +148,8 @@ export async function init(): Promise<void> {
|
|||||||
await services.restoreProcessesFromDB();
|
await services.restoreProcessesFromDB();
|
||||||
await services.restoreSecretsFromDB();
|
await services.restoreSecretsFromDB();
|
||||||
|
|
||||||
// If we have a service redirection flag, we intercept it here
|
// We register all the event listeners
|
||||||
const endpoint = window.location.pathname;
|
await registerAllListeners();
|
||||||
|
|
||||||
if (endpoint) {
|
|
||||||
await handleSource(endpoint);
|
|
||||||
} else {
|
|
||||||
console.log('No endpoint provided');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (services.isPaired()) {
|
if (services.isPaired()) {
|
||||||
await navigate('account');
|
await navigate('account');
|
||||||
@ -167,82 +162,293 @@ export async function init(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleSource(endpoint: string) {
|
export async function registerAllListeners() {
|
||||||
const services = await Services.getInstance();
|
const services = await Services.getInstance();
|
||||||
|
|
||||||
switch (endpoint) {
|
const errorResponse = (errorMsg: string, origin: string) => {
|
||||||
case '/link-service':
|
window.parent.postMessage(
|
||||||
window.addEventListener('message', async (event: MessageEvent) => {
|
{
|
||||||
console.log("Received message:", event.data);
|
type: MessageType.ERROR,
|
||||||
if (event.data.type === 'REQUEST_LINK') {
|
error: errorMsg
|
||||||
console.log("Received link request, showing confirmation modal");
|
},
|
||||||
|
origin
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const modalService = await ModalService.getInstance();
|
const handleRequestLink = async (event: MessageEvent) => {
|
||||||
const result = await modalService.showConfirmationModal({
|
if (event.data.type !== MessageType.REQUEST_LINK) {
|
||||||
title: 'Confirmation de liaison',
|
return;
|
||||||
content: `
|
}
|
||||||
<div class="modal-confirmation">
|
const modalService = await ModalService.getInstance();
|
||||||
<h3>Liaison avec ${event.origin}</h3>
|
const result = await modalService.showConfirmationModal({
|
||||||
<p>Vous êtes sur le point de lier votre identité 4NK avec ${event.origin}.</p>
|
title: 'Confirmation de liaison',
|
||||||
<p>Cette action permettra à ${event.origin} d'intéragir avec votre identité 4NK.</p>
|
content: `
|
||||||
<p>Voulez-vous continuer ?</p>
|
<div class="modal-confirmation">
|
||||||
</div>
|
<h3>Liaison avec ${event.origin}</h3>
|
||||||
`,
|
<p>Vous êtes sur le point de lier l'identité numérique de la clé securisée propre à votre appareil avec ${event.origin}.</p>
|
||||||
confirmText: 'Ajouter un service',
|
<p>Cette action permettra à ${event.origin} d'intéragir avec votre appareil.</p>
|
||||||
cancelText: 'Annuler'
|
<p>Voulez-vous continuer ?</p>
|
||||||
});
|
</div>
|
||||||
|
`,
|
||||||
|
confirmText: 'Ajouter un service',
|
||||||
|
cancelText: 'Annuler'
|
||||||
|
});
|
||||||
|
|
||||||
if (result) {
|
try {
|
||||||
try {
|
if (!result) {
|
||||||
if (!services.isPaired()) {
|
throw new Error('User refused to link');
|
||||||
await prepareAndSendPairingTx();
|
}
|
||||||
await services.confirmPairing();
|
|
||||||
}
|
|
||||||
|
|
||||||
const neuteredDevice = services.dumpNeuteredDevice();
|
const tokenService = await TokenService.getInstance();
|
||||||
if (neuteredDevice) {
|
const sessionToken = tokenService.generateSessionToken(event.origin);
|
||||||
window.parent.postMessage(
|
|
||||||
{
|
if (services.isPaired()) {
|
||||||
type: 'RESPONSE',
|
// Device already paired - just renew token
|
||||||
success: true,
|
window.parent.postMessage(
|
||||||
payload: JSON.stringify(neuteredDevice)
|
{
|
||||||
},
|
type: MessageType.RENEW_TOKEN,
|
||||||
event.origin
|
sessionToken
|
||||||
);
|
},
|
||||||
} else {
|
event.origin
|
||||||
throw new Error('Failed to get a neutered device');
|
);
|
||||||
}
|
} else {
|
||||||
} catch (error) {
|
// New device - do pairing process
|
||||||
window.parent.postMessage(
|
await prepareAndSendPairingTx();
|
||||||
{
|
await services.confirmPairing();
|
||||||
type: 'RESPONSE',
|
const neuteredDevice = services.dumpNeuteredDevice();
|
||||||
success: false,
|
|
||||||
error: 'Failed to complete pairing process'
|
if (!neuteredDevice) {
|
||||||
},
|
throw new Error('Failed to get neutered device');
|
||||||
event.origin
|
}
|
||||||
);
|
|
||||||
}
|
window.parent.postMessage(
|
||||||
} else {
|
{
|
||||||
// The user canceled the link request
|
type: MessageType.LINK_ACCEPTED,
|
||||||
console.log("User canceled the linking process");
|
payload: JSON.stringify(neuteredDevice),
|
||||||
window.parent.postMessage(
|
sessionToken
|
||||||
{
|
},
|
||||||
type: 'RESPONSE',
|
event.origin
|
||||||
success: false,
|
);
|
||||||
error: 'User canceled linking'
|
}
|
||||||
},
|
} catch (error) {
|
||||||
event.origin
|
const errorMsg = `Failed to link service: ${error}`;
|
||||||
);
|
errorResponse(errorMsg, event.origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddProfile = async (event: MessageEvent) => {
|
||||||
|
if (event.data.type !== MessageType.CREATE_PROFILE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tokenService = await TokenService.getInstance();
|
||||||
|
const services = await Services.getInstance();
|
||||||
|
|
||||||
|
if (!services.isPaired()) {
|
||||||
|
const errorMsg = 'Device not paired';
|
||||||
|
errorResponse(errorMsg, event.origin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { profileData, token } = event.data;
|
||||||
|
|
||||||
|
// Validate the session token
|
||||||
|
if (!token || !tokenService.validateToken(token, event.origin)) {
|
||||||
|
throw new Error('Invalid or expired session token');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create profile
|
||||||
|
await services.createAndSendProfileTx(profileData);
|
||||||
|
|
||||||
|
window.parent.postMessage(
|
||||||
|
{
|
||||||
|
type: MessageType.PROFILE_CREATED,
|
||||||
|
token // Resend the same token
|
||||||
|
},
|
||||||
|
event.origin
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
const errorMsg = `Failed to create profile: ${e}`;
|
||||||
|
errorResponse(errorMsg, event.origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleAddFolder = async (event: MessageEvent) => {
|
||||||
|
if (event.data.type !== MessageType.CREATE_FOLDER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tokenService = await TokenService.getInstance();
|
||||||
|
const services = await Services.getInstance();
|
||||||
|
|
||||||
|
if (!services.isPaired()) {
|
||||||
|
const errorMsg = 'Device not paired';
|
||||||
|
errorResponse(errorMsg, event.origin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data, token } = event.data;
|
||||||
|
|
||||||
|
if (!token || !tokenService.validateToken(token, event.origin)) {
|
||||||
|
throw new Error('Invalid or expired session token');
|
||||||
|
}
|
||||||
|
|
||||||
|
await services.createAndSendFolderTx(data);
|
||||||
|
|
||||||
|
window.parent.postMessage(
|
||||||
|
{
|
||||||
|
type: MessageType.FOLDER_CREATED,
|
||||||
|
token
|
||||||
|
},
|
||||||
|
event.origin
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
const errorMsg = `Failed to create folder: ${e}`;
|
||||||
|
errorResponse(errorMsg, event.origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// We got a state for some process and return as many clear attributes as we can
|
||||||
|
const handleDecryptState = async (event: MessageEvent) => {
|
||||||
|
if (event.data.type !== MessageType.RETRIEVE_DATA) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tokenService = await TokenService.getInstance();
|
||||||
|
const services = await Services.getInstance();
|
||||||
|
|
||||||
|
if (!services.isPaired()) {
|
||||||
|
const errorMsg = 'Device not paired';
|
||||||
|
errorResponse(errorMsg, event.origin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { processId, stateId, token } = event.data;
|
||||||
|
|
||||||
|
if (!token || !tokenService.validateToken(token, event.origin)) {
|
||||||
|
throw new Error('Invalid or expired session token');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the state for the process
|
||||||
|
const process = await services.getProcess(processId);
|
||||||
|
const state = services.getStateFromId(process, stateId);
|
||||||
|
|
||||||
|
let res: Record<string, string> = {};
|
||||||
|
if (state) {
|
||||||
|
// Decrypt all the data we have the key for
|
||||||
|
for (const attribute of Object.keys(state.pcd_commitment)) {
|
||||||
|
const decryptedAttribute = await services.decryptAttribute(processId, state, attribute);
|
||||||
|
if (decryptedAttribute) {
|
||||||
|
res[attribute] = decryptedAttribute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
console.log('sending message from link-service');
|
throw new Error('Unknown state for process', processId);
|
||||||
window.parent.postMessage({ type: 'LISTENING', endpoint: endpoint }, '*');
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
window.parent.postMessage(
|
||||||
console.log('Unknown endpoint:', endpoint);
|
{
|
||||||
|
type: MessageType.DATA_RETRIEVED,
|
||||||
|
data: JSON.stringify(res),
|
||||||
|
token
|
||||||
|
},
|
||||||
|
event.origin
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
const errorMsg = `Failed to retrieve data: ${e}`;
|
||||||
|
errorResponse(errorMsg, event.origin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleGetProfile = async (event: MessageEvent) => {
|
||||||
|
if (event.data.type !== MessageType.RETRIEVE_DATA) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tokenService = await TokenService.getInstance();
|
||||||
|
const services = await Services.getInstance();
|
||||||
|
|
||||||
|
if (!services.isPaired()) {
|
||||||
|
const errorMsg = 'Device not paired';
|
||||||
|
errorResponse(errorMsg, event.origin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('📥 [GetProfile] Réception de la demande');
|
||||||
|
const { sessionToken } = event.data;
|
||||||
|
|
||||||
|
if (!sessionToken || !tokenService.validateToken(sessionToken, event.origin)) {
|
||||||
|
throw new Error('Invalid or expired session token');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔍 [GetProfile] Récupération des profils');
|
||||||
|
const processes = await services.getProcesses();
|
||||||
|
console.log('Processes après résolution:', processes);
|
||||||
|
|
||||||
|
let decryptedData: Record<string, string> = {};
|
||||||
|
|
||||||
|
const processArray = Array.isArray(processes) ? processes : Object.values(processes);
|
||||||
|
|
||||||
|
if (processArray && processArray.length > 0) {
|
||||||
|
console.log(`📋 Traitement de ${processArray.length} processus`);
|
||||||
|
|
||||||
|
for (const process of processArray) {
|
||||||
|
try {
|
||||||
|
console.log('Process en cours:', process);
|
||||||
|
if (process && process.id && !process.certified) {
|
||||||
|
console.log(`🔄 Traitement du processus non certifié ${process.id}`);
|
||||||
|
const states = process.states;
|
||||||
|
|
||||||
|
if (states && states.length > 0) {
|
||||||
|
for (const state of states) {
|
||||||
|
if (state && state.pcd_commitment) {
|
||||||
|
console.log(`📝 Attributs trouvés dans l'état:`, Object.keys(state.pcd_commitment));
|
||||||
|
for (const attribute of Object.keys(state.pcd_commitment)) {
|
||||||
|
try {
|
||||||
|
const decryptedValue = await services.decryptAttribute(process.id, state, attribute);
|
||||||
|
if (decryptedValue) {
|
||||||
|
decryptedData[attribute] = decryptedValue;
|
||||||
|
console.log(`✅ Attribut déchiffré: ${attribute} = ${decryptedValue}`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`⚠️ Échec du déchiffrement de ${attribute}:`, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (processError) {
|
||||||
|
console.error(`❌ Erreur lors du traitement du processus:`, processError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('❌ Aucun processus trouvé ou tableau vide');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('📤 [GetProfile] Données déchiffrées:', decryptedData);
|
||||||
|
window.parent.postMessage(
|
||||||
|
{
|
||||||
|
type: MessageType.DATA_RETRIEVED,
|
||||||
|
data: decryptedData,
|
||||||
|
sessionToken
|
||||||
|
},
|
||||||
|
event.origin
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('❌ Erreur:', e);
|
||||||
|
errorResponse(`Failed to get profile: ${e}`, event.origin);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('message', handleRequestLink);
|
||||||
|
window.addEventListener('message', handleAddProfile);
|
||||||
|
window.addEventListener('message', handleAddFolder);
|
||||||
|
window.addEventListener('message', handleDecryptState);
|
||||||
|
window.addEventListener('message', handleGetProfile);
|
||||||
|
|
||||||
|
window.parent.postMessage({ type: 'LISTENING' }, '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function cleanPage() {
|
async function cleanPage() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user