import backgroundImage from "@Assets/images/background_refonte.svg"; import CoffreIcon from "@Assets/logo_small_blue.svg"; import Auth from "@Front/Api/Auth/IdNot"; import Loader from "@Front/Components/DesignSystem/Loader"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import HelpBox from "@Front/Components/Elements/HelpBox"; import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage"; import Module from "@Front/Config/Module"; import UserStore from "@Front/Stores/UserStore"; import CookieService from "@Front/Services/CookieService/CookieService"; import Image from "next/image"; import { useRouter } from "next/router"; import React, { useEffect, useState } from "react"; import classes from "./classes.module.scss"; // Importer les composants de UI pour les barres de progression import { LinearProgress, Box, Typography as MuiTypography } from "@mui/material"; import AuthModal from "src/sdk/AuthModal"; import MessageBus from "src/sdk/MessageBus"; import Iframe from "src/sdk/Iframe"; import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; import { ProgressInfo } from "src/common/Api/LeCoffreApi/sdk/ImportData"; export default function LoginCallBack() { const router = useRouter(); const [isAuthModalOpen, setIsAuthModalOpen] = useState(false); const [isConnected, setIsConnected] = useState(false); // États pour les barres de progression const [showProgress, setShowProgress] = useState(false); const [progressInfo, setProgressInfo] = useState({ globalProgress: 0, currentStep: '', stepProgress: 0, description: '' }); const waitForUserInfo = (): Promise => { return new Promise((resolve, reject) => { if (UserStore.instance.getUser()) { resolve(UserStore.instance.getUser()); return; } // Poll for userInfo every 100ms const checkInterval = setInterval(() => { if (UserStore.instance.getUser()) { clearInterval(checkInterval); resolve(UserStore.instance.getUser()); } }, 100); // Timeout after 60 seconds setTimeout(() => { clearInterval(checkInterval); reject(new Error('Timeout waiting for user info')); }, 60000); }); }; useEffect(() => { async function getUser() { UserStore.instance.disconnect(); // TODO: review // HACK: If start with http://local.lecoffreio.4nkweb:3000/authorized-client // Replace with http://localhost:3000/authorized-client if (window.location.href.startsWith('http://local.lecoffreio.4nkweb')) { window.location.href = window.location.href.replace('http://local.lecoffreio.4nkweb:3000/authorized-client', 'http://localhost:3000/authorized-client'); return; } const code = router.query["code"]; if (code) { try { // Nettoyer l'URL pour ne garder que la racine const rootUrl = window.location.origin; if (window.location.href !== rootUrl) { window.history.replaceState({}, document.title, rootUrl); } const user: any = await Auth.getInstance().idNotAuth(code as string); // Extract both user data and auth token from the response const { idNotUser, authToken } = user; if (!authToken) { console.error('[LoginCallback] No authToken received from backend'); return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } // Store the auth token for API authentication // TODO The authToken is just a uuid for now, it's very broken CookieService.getInstance().setCookie("leCoffreAccessToken", authToken); // Test that we can get user info and the authToken works // TODO test that what's returned is identical to what we got before const userInfoResponse = await Auth.getInstance().getIdNotUser(); console.log('[LoginCallback] userInfoResponse:', userInfoResponse); if (!userInfoResponse || !userInfoResponse.success || !userInfoResponse.data) { console.error('[LoginCallback] No userInfo received from backend'); return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } // Store user info as a cookie CookieService.getInstance().setCookie("leCoffreUserInfo", JSON.stringify(userInfoResponse.data)); setIsAuthModalOpen(true); console.log('[LoginCallback] authToken stored successfully'); return; } catch (e: any) { if (e.http_status === 401 && e.message === "Email not found") { return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=3"); } if (e.http_status === 409) { return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=4"); } return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } } return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=2"); } getUser(); }, [router]); return (
coffre Connexion à votre espace professionnel
{!showProgress ? ( ) : ( Importation des données {/* Progression globale */} Progression globale: {Math.round(progressInfo.globalProgress)}% {progressInfo.currentStep} {/* Progression par étape */} Progression de l'étape: {Math.round(progressInfo.stepProgress)}% {progressInfo.description || ''} )}
{isAuthModalOpen && { setIsAuthModalOpen(false); setIsConnected(true); setTimeout(() => { LoaderService.getInstance().show(); MessageBus.getInstance().initMessageListener(); MessageBus.getInstance().isReady().then(async () => { try { const userInfo = await waitForUserInfo(); if (!userInfo) { console.error('[LoginCallback] No userInfo received from backend'); return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } // console.log('userInfo : ', userInfo); // Here we are now authenticated with idNot, we have our idnot user info // We also have a device and it should be paired // What we may not have yet is a collaborator process // Office may not have a process too let collaboratorProcess: { processId: string, processData: { [key: string]: any } } | null = null; let officeProcess: { processId: string, processData: { [key: string]: any } } | null = null; // Initialize collaborator process try { // Wait for pairing ID to be available before proceeding const pairingId = await MessageBus.getInstance().getPairingId(); console.log('[LoginCallback] Pairing ID obtained:', pairingId); // Check if we are part of the right collaborator process const myCollaboratorProcessesData = await MessageBus.getInstance().getProcessesDecoded((processId: string, values: { [key: string]: any }) => { return values['utype'] === 'collaborator' && values['idNot'] === userInfo.idNot && values['isDeleted'] === 'false'; }); if (myCollaboratorProcessesData && Object.keys(myCollaboratorProcessesData).length !== 0) { collaboratorProcess = { processId: Object.keys(myCollaboratorProcessesData)[0]!, processData: Object.values(myCollaboratorProcessesData)[0]! }; } else { const res = await Auth.getInstance().getUserProcessByIdNot(pairingId); if (res.success) { collaboratorProcess = res.data; } else { console.error('[LoginCallback] Error getting collaborator process'); router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); return; } // await new Promise(resolve => setTimeout(resolve, 100)); } // If we're on a new device, signer should notice and add us to the process // TODO check that we're part of the collaborator process } catch (error: any) { console.error('[LoginCallback] Error getting collaborator process:', error); if (error.message === 'Timeout waiting for pairing ID') { console.error('[LoginCallback] Pairing ID not available after timeout'); return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } // If we can't get collaborator process, we can't proceed return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } // Initialize office process try { // Wait for pairing ID to be available before proceeding const pairingId = await MessageBus.getInstance().getPairingId(); console.log('[LoginCallback] Pairing ID obtained:', pairingId); // Now we need to check for office process const myOfficeProcessesData = await MessageBus.getInstance().getProcessesDecoded((processId: string, values: { [key: string]: any }) => { return values['utype'] === 'office' && values['idNot'] === userInfo.office.idNot && values['isDeleted'] === 'false'; }); if (myOfficeProcessesData && Object.keys(myOfficeProcessesData).length !== 0) { officeProcess = { processId: Object.keys(myOfficeProcessesData)[0]!, processData: Object.values(myOfficeProcessesData)[0]! }; } else { const res = await Auth.getInstance().getUserProcessByIdNot(pairingId); if (res.success) { officeProcess = res.data; } else { console.error('[LoginCallback] Error getting collaborator process'); router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); return; } } // TODO Check that we're part of the office process // For now we rely on the signer to get office data, for the sake of simplicity } catch (error: any) { console.error('[LoginCallback] Error getting office process:', error); return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } // Verify both processes are initialized before proceeding if (!collaboratorProcess || !officeProcess) { console.error('[LoginCallback] Failed to initialize required processes'); router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); return; } if (!UserStore.instance.connect(collaboratorProcess.processData, officeProcess.processData)) { console.error('[LoginCallback] collaborator not connected'); router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); return; } window.location.href = Module.getInstance().get().modules.pages.Folder.props.path; } catch (error) { console.error('[LoginCallback] Error waiting for user info or processing collaborator:', error); router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } finally { MessageBus.getInstance().destroyMessageListener(); LoaderService.getInstance().hide(); } return; }); }, 100); }} />} {isConnected &&