diff --git a/src/common/Api/LeCoffreApi/sdk/CollaboratorService.ts b/src/common/Api/LeCoffreApi/sdk/CollaboratorService.ts index 81ac8469..6c023c66 100644 --- a/src/common/Api/LeCoffreApi/sdk/CollaboratorService.ts +++ b/src/common/Api/LeCoffreApi/sdk/CollaboratorService.ts @@ -4,9 +4,6 @@ import User from 'src/sdk/User'; import AbstractService from './AbstractService'; -import OfficeService from './OfficeService'; -import RoleService from './RoleService'; -import OfficeRoleService from './OfficeRoleService'; import { DEFAULT_STORAGE_URLS } from '@Front/Config/AppConstants'; export default class CollaboratorService extends AbstractService { @@ -15,7 +12,7 @@ export default class CollaboratorService extends AbstractService { super(); } - public static createCollaborator(collaboratorData: any, validatorId: string): Promise { + public static async createCollaborator(collaboratorData: any, validatorId: string): Promise<{ processId: string, processData: any }> { const ownerId: string = User.getInstance().getPairingId()!; const processData: any = { @@ -28,134 +25,85 @@ export default class CollaboratorService extends AbstractService { }; const privateFields: string[] = Object.keys(processData); - privateFields.splice(privateFields.indexOf('uid'), 1); - privateFields.splice(privateFields.indexOf('utype'), 1); - privateFields.splice(privateFields.indexOf('isDeleted'), 1); + const allFields: string[] = [...privateFields, 'roles']; const roles: any = { demiurge: { - members: [ownerId], + members: [ownerId, validatorId], validation_rules: [], storages: [] }, owner: { - members: [ownerId], + members: [ownerId, validatorId], validation_rules: [ { - quorum: 1, - fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'], - min_sig_member: 1, - }, - ], - storages: [...DEFAULT_STORAGE_URLS] - }, - validator: { - members: [validatorId], - validation_rules: [ - { - quorum: 1, - fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'], - min_sig_member: 1, + quorum: 0.01, + fields: allFields, + min_sig_member: 0.01, }, ], storages: [...DEFAULT_STORAGE_URLS] }, apophis: { - members: [ownerId], + members: [ownerId, validatorId], validation_rules: [], storages: [] } }; - return new Promise((resolve: (processCreated: any) => void, reject: (error: string) => void) => { - this.messageBus.createProcess(processData, privateFields, roles).then((processCreated: any) => { - this.messageBus.notifyUpdate(processCreated.processId, processCreated.process.states[0].state_id).then(() => { - this.messageBus.validateState(processCreated.processId, processCreated.process.states[0].state_id).then((_stateValidated: any) => { - this.getCollaboratorByUid(processCreated.processData.uid).then(resolve).catch(reject); - }).catch(reject); - }).catch(reject); - }).catch(reject); - }); + try { + const processCreated = await this.messageBus.createProcess(processData, privateFields, roles); + await this.messageBus.notifyUpdate(processCreated.processId, processCreated.process.states[0].state_id); + await this.messageBus.validateState(processCreated.processId, processCreated.process.states[0].state_id); + const finalProcessData = await this.messageBus.getProcessData(processCreated.processId); + return { processId: processCreated.processId, processData: finalProcessData }; + } catch (error) { + throw error; + } } - public static getCollaborators(callback: (processes: any[]) => void, waitForAll: boolean = false): void { - // Check if we have valid cache - const items: any[] = this.getItems('_collaborators_'); - if (items.length > 0 && !waitForAll) { - setTimeout(() => callback([...items]), 0); + public static getCollaborators(callback: (processes: Record) => void): void { + const items: Record = this.getItems('_collaborators_'); + if (Object.keys(items).length > 0) { + setTimeout(() => callback(items), 0); } - this.messageBus.getProcessesDecoded((publicValues: any) => - publicValues['uid'] && - publicValues['utype'] && - publicValues['utype'] === 'collaborator' && - publicValues['isDeleted'] && - publicValues['isDeleted'] === 'false' && - !items.map((item: any) => item.processData.uid).includes(publicValues['uid']) - ).then(async (processes: any[]) => { - if (processes.length === 0) { - if (waitForAll) { - callback([...items]); + this.messageBus.getProcessesDecoded((processId: string, data: any) => + data['utype'] && + data['utype'] === 'collaborator' && + data['isDeleted'] && + data['isDeleted'] === 'false' && + !Object.keys(items).includes(processId) + ).then(async (processesData: Record) => { + if (Object.keys(processesData).length === 0) { + // If no new processes and no cached items, return empty array + if (Object.keys(items).length === 0) { + callback([]); } return; } - const updatedItems: any[] = [...items]; - - for (let processIndex = 0; processIndex < processes.length; processIndex++) { - let process = processes[processIndex]; - - if (!waitForAll) { - process = await this.completeCollaborator(process, (processInProgress: any) => { - const currentItems: any[] = [...updatedItems]; - - const existingIndex: number = currentItems.findIndex(item => item.processData?.uid === processInProgress.processData?.uid); - if (existingIndex >= 0) { - currentItems[existingIndex] = processInProgress; - } else { - currentItems.push(processInProgress); - } - - callback(currentItems); - }); - } else { - process = await this.completeCollaborator(process); - } - - // Update cache - this.setItem('_collaborators_', process); - - const existingIndex: number = updatedItems.findIndex(item => item.processData?.uid === process.processData?.uid); - if (existingIndex >= 0) { - updatedItems[existingIndex] = process; - } else { - updatedItems.push(process); - } - - if (!waitForAll) { - callback([...updatedItems]); - } - } - - if (waitForAll) { - callback([...updatedItems]); - } + // Single callback with all completed items + callback(items); + }).catch(error => { + console.error('Failed to fetch collaborators:', error); + // Return cached data if available, otherwise empty array + callback(items); }); } - public static getCollaboratorsBy(whereClause: { [path: string]: any }): Promise { - return new Promise((resolve: (collaborators: any[]) => void) => { - this.getCollaborators((processes: any[]) => { - if (processes.length === 0) { - resolve([]); + public static getCollaboratorsBy(whereClause: { [path: string]: any }): Promise> { + return new Promise>((resolve: (collaborators: Record) => void) => { + this.getCollaborators((processes: Record) => { + if (Object.keys(processes).length === 0) { + resolve({}); } else { - resolve(processes.filter((process: any) => { - const collaborator: any = process.processData; - + const filteredEntries = Object.entries(processes).filter(([processId, process]) => { for (const path in whereClause) { const paths: string[] = path.split('.'); - let value: any = collaborator; + let value: any = process; + value['processId'] = processId; for (let i = 0; i < paths.length; i++) { const currentPath = paths[i]; if (!currentPath || value === undefined || value === null) { @@ -170,19 +118,28 @@ export default class CollaboratorService extends AbstractService { } return true; - })); + }); + + // Convert filtered entries back to a Record + const filteredProcesses: Record = {}; + filteredEntries.forEach(([processId, process]) => { + filteredProcesses[processId] = process; + }); + + resolve(filteredProcesses); } - }, true); + }); }); } public static getCollaboratorBy(whereClause: { [path: string]: any }): Promise { return new Promise((resolve: (collaborator: any | null) => void) => { - this.getCollaborators((processes: any[]) => { - if (processes.length === 0) { + this.getCollaborators((processes: Record) => { + const processArray = Object.values(processes); + if (processArray.length === 0) { resolve(null); } else { - resolve(processes.find((process: any) => { + resolve(processArray.find((process: any) => { const collaborator: any = process.processData; for (const path in whereClause) { @@ -205,120 +162,30 @@ export default class CollaboratorService extends AbstractService { return true; })); } - }, true); + }); }); } - public static getCollaboratorByUid(uid: string, forceRefresh: boolean = false): Promise { - // Check if we have valid cache - const item: any = this.getItem('_collaborators_', uid); - if (item && !forceRefresh) { - return Promise.resolve(item); + public static async updateCollaborator(processId: string, newData: any): Promise { + try { + const processUpdated = await this.messageBus.updateProcess( + processId, + { updated_at: new Date().toISOString(), ...newData }, + [], + null + ); + + const newStateId: string = processUpdated.diffs[0]?.state_id; + await this.messageBus.notifyUpdate(processId, newStateId); + await this.messageBus.validateState(processId, newStateId); + + const processData = await this.messageBus.getProcessData(processId); + + // Update cache + this.setItem('_collaborators_', processId, processData); + } catch (error) { + console.error('Failed to update collaborator:', error); + throw error; // Re-throw to allow caller to handle } - - return new Promise((resolve: (process: any) => void, reject: (error: string) => void) => { - this.messageBus.getProcessesDecoded((publicValues: any) => - publicValues['uid'] && - publicValues['uid'] === uid && - publicValues['utype'] && - publicValues['utype'] === 'collaborator' && - publicValues['isDeleted'] && - publicValues['isDeleted'] === 'false' - ).then(async (processes: any[]) => { - if (processes.length === 0) { - resolve(null); - } else { - let process: any = processes[0]; - process = await this.completeCollaborator(process); - - // Update cache - this.setItem('_collaborators_', process); - - resolve(process); - } - }).catch(reject); - }); - } - - public static updateCollaborator(process: any, newData: any): Promise { - return new Promise((resolve: () => void, reject: (error: string) => void) => { - this.messageBus.updateProcess(process.processId, { updated_at: new Date().toISOString(), ...newData }, [], null).then((processUpdated: any) => { - const newStateId: string = processUpdated.diffs[0]?.state_id; - this.messageBus.notifyUpdate(process.processId, newStateId).then(() => { - this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => { - const collaboratorUid: string = process.processData.uid; - this.removeItem('_collaborators_', collaboratorUid); - - this.getCollaboratorByUid(collaboratorUid, true).then(resolve).catch(reject); - }).catch(reject); - }).catch(reject); - }).catch(reject); - }); - } - - private static async completeCollaborator(process: any, progressCallback?: (processInProgress: any) => void): Promise { - const progressiveProcess: any = JSON.parse(JSON.stringify(process)); - - if (process.processData.office) { - const office: any = (await OfficeService.getOfficeByUid(process.processData.office.uid)).processData; - if (office) { - process.processData.office = { - uid: office.uid, - idNot: office.idNot, - crpcen: office.crpcen, - name: office.name, - office_status: office.office_status - }; - - if (progressCallback) { - progressiveProcess.processData.office = process.processData.office; - progressCallback(JSON.parse(JSON.stringify(progressiveProcess))); - } - } else { - console.error('Office not found'); - } - } - - if (process.processData.role) { - const role: any = (await RoleService.getRoleByUid(process.processData.role.uid)).processData; - if (!role) { - console.error('Role not found'); - } else { - process.processData.role = { - uid: role.uid, - name: role.name - }; - } - - if (progressCallback) { - progressiveProcess.processData.role = process.processData.role; - progressCallback(JSON.parse(JSON.stringify(progressiveProcess))); - } - } - - if (process.processData.office_role) { - const officeRole: any = (await OfficeRoleService.getOfficeRoleByUid(process.processData.office_role.uid)).processData; - if (!officeRole) { - console.error('Office role not found'); - } else { - process.processData.office_role = { - uid: officeRole.uid, - name: officeRole.name, - rules: officeRole.rules?.map((rule: any) => { - return { - uid: rule.uid, - name: rule.name - }; - }) - }; - } - - if (progressCallback) { - progressiveProcess.processData.office_role = process.processData.office_role; - progressCallback(JSON.parse(JSON.stringify(progressiveProcess))); - } - } - - return process; } } diff --git a/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts b/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts index 9f67c8ac..251825dc 100644 --- a/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts +++ b/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts @@ -21,6 +21,7 @@ export default class DeedTypeService extends AbstractService { isDeleted: 'false', created_at: new Date().toISOString(), updated_at: new Date().toISOString(), + document_types: [], ...deedTypeData }; @@ -63,39 +64,36 @@ export default class DeedTypeService extends AbstractService { } } - public static getDeedTypes(callback: (processes: any[]) => void): void { + public static getDeedTypes(callback: (processes: Record) => void): void { // Check if we have valid cache - const items: any[] = this.getItems('_deed_types_'); - if (items.length > 0) { - setTimeout(() => callback([...items]), 0); + const items: Record = this.getItems('_deed_types_'); + if (Object.keys(items).length > 0) { + setTimeout(() => callback(items), 0); } - this.messageBus.getProcessesDecoded((values: any) => { - return values['utype'] === 'deedType' + this.messageBus.getProcessesDecoded((_processId: string, values: any) => { + return values['utype'] + && values['utype'] === 'deedType' + && values['isDeleted'] && values['isDeleted'] === 'false'; - }).then(async (processes: any) => { - if (processes.length === 0) { - callback([...items]); + }).then(async (processes: Record) => { + if (Object.keys(processes).length === 0) { + callback(items); return; } - const updatedItems: any[] = [...items]; + console.log('[DeedTypeService/getDeedTypes] processes', processes); - for (let processIndex = 0; processIndex < processes.length; processIndex++) { - const process = processes[processIndex]; - + const updatedItems: Record = { ...items }; + + for (const [processId, process] of Object.entries(processes)) { // Update cache - this.setItem('_deed_types_', process); + this.setItem('_deed_types_', processId, process); - const existingIndex: number = updatedItems.findIndex(item => item.processData?.uid === process.processData?.uid); - if (existingIndex >= 0) { - updatedItems[existingIndex] = process; - } else { - updatedItems.push(process); - } + updatedItems[processId] = process; } - callback([...updatedItems]); + callback(updatedItems); }); } @@ -115,7 +113,7 @@ export default class DeedTypeService extends AbstractService { const processData = await this.messageBus.getProcessData(processId); // Update cache - this.setItem('_deed_types_', processData); + this.setItem('_deed_types_', processId, processData); } catch (error) { console.error('Failed to update deed type:', error); throw error; // Re-throw to allow caller to handle diff --git a/src/common/Api/LeCoffreApi/sdk/DocumentTypeService.ts b/src/common/Api/LeCoffreApi/sdk/DocumentTypeService.ts index 6bab2586..40995ba6 100644 --- a/src/common/Api/LeCoffreApi/sdk/DocumentTypeService.ts +++ b/src/common/Api/LeCoffreApi/sdk/DocumentTypeService.ts @@ -63,106 +63,55 @@ export default class DocumentTypeService extends AbstractService { }); } - public static getDocumentTypes(callback: (processes: any[]) => void): void { + public static getDocumentTypes(callback: (processes: Record) => void): void { // Check if we have valid cache - const items: any[] = this.getItems('_document_types_'); - if (items.length > 0) { - setTimeout(() => callback([...items]), 0); + const items: Record = this.getItems('_document_types_'); + if (Object.keys(items).length > 0) { + setTimeout(() => callback(items), 0); } - this.messageBus.getProcessesDecoded((values: any) => { + this.messageBus.getProcessesDecoded((_processId: string, values: any) => { return values['utype'] === 'documentType' && values['isDeleted'] === 'false'; - }).then(async (processes: any) => { - if (processes.length === 0) { - callback([...items]); + }).then(async (processes: Record) => { + if (Object.keys(processes).length === 0) { + callback(items); return; } - const updatedItems: any[] = [...items]; + const updatedItems: Record = { ...items }; - for (let processIndex = 0; processIndex < processes.length; processIndex++) { - const process = processes[processIndex]; - + for (const [processId, process] of Object.entries(processes)) { // Update cache - this.setItem('_document_types_', process); + this.setItem('_document_types_', processId, process); - const existingIndex: number = updatedItems.findIndex(item => item.processId === process.processId); - if (existingIndex >= 0) { - updatedItems[existingIndex] = process; - } else { - updatedItems.push(process); - } + updatedItems[processId] = process; } - callback([...updatedItems]); + callback(updatedItems); }); } - public static getDocumentTypeByProcessId(processId: string): Promise { - // Check if we have valid cache - const item: any = this.getItem('_document_types_', processId); - if (item) { - return Promise.resolve(item); + public static async updateDocumentType(processId: string, newData: any): Promise { + try { + const processUpdated = await this.messageBus.updateProcess( + processId, + { updated_at: new Date().toISOString(), ...newData }, + [], + null + ); + + const newStateId: string = processUpdated.diffs[0]?.state_id; + await this.messageBus.notifyUpdate(processId, newStateId); + await this.messageBus.validateState(processId, newStateId); + + const processData = await this.messageBus.getProcessData(processId); + + // Update cache + this.setItem('_document_types_', processId, processData); + } catch (error) { + console.error('Failed to update deed type:', error); + throw error; // Re-throw to allow caller to handle } - - return new Promise((resolve: (process: any) => void, reject: (error: string) => void) => { - this.messageBus.getProcessesDecoded((publicValues: any) => { - return publicValues['utype'] === 'documentType' && publicValues['isDeleted'] === 'false'; - }).then((processes: any[]) => { - // Find the process with matching processId - const process = processes.find((p: any) => p.processId === processId); - - if (!process) { - resolve(null); - return; - } - - // Update cache - this.setItem('_document_types_', process); - - resolve(process); - }).catch(reject); - }); - } - - // Keep the old method for backward compatibility but mark as deprecated - /** @deprecated Use getDocumentTypeByProcessId instead */ - public static getDocumentTypeByUid(uid: string): Promise { - // Check if we have valid cache - const item: any = this.getItem('_document_types_', uid); - if (item) { - return Promise.resolve(item); - } - - return new Promise((resolve: (process: any) => void, reject: (error: string) => void) => { - this.messageBus.getProcessesDecoded((publicValues: any) => publicValues['uid'] && publicValues['uid'] === uid && publicValues['utype'] && publicValues['utype'] === 'documentType' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false').then((processes: any[]) => { - if (processes.length === 0) { - resolve(null); - } else { - const process: any = processes[0]; - - // Update cache - this.setItem('_document_types_', process); - - resolve(process); - } - }).catch(reject); - }); - } - - public static updateDocumentType(process: any, newData: any): Promise { - return new Promise((resolve: () => void, reject: (error: string) => void) => { - this.messageBus.updateProcess(process.processId, { updated_at: new Date().toISOString(), ...newData }, [], null).then((processUpdated: any) => { - const newStateId: string = processUpdated.diffs[0]?.state_id; - this.messageBus.notifyUpdate(process.processId, newStateId).then(() => { - this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => { - this.removeItem('_document_types_', process.processId); - - this.getDocumentTypeByProcessId(process.processId).then(resolve).catch(reject); - }).catch(reject); - }).catch(reject); - }).catch(reject); - }); } } diff --git a/src/common/Api/LeCoffreApi/sdk/FolderService.ts b/src/common/Api/LeCoffreApi/sdk/FolderService.ts index 9413cc73..41cb6d11 100644 --- a/src/common/Api/LeCoffreApi/sdk/FolderService.ts +++ b/src/common/Api/LeCoffreApi/sdk/FolderService.ts @@ -3,13 +3,7 @@ import { v4 as uuidv4 } from 'uuid'; import User from 'src/sdk/User'; import AbstractService from './AbstractService'; -import CustomerService from './CustomerService'; -import CollaboratorService from './CollaboratorService'; -import DeedTypeService from './DeedTypeService'; -import DocumentTypeService from './DocumentTypeService'; -import DocumentService from './DocumentService'; -import FileService from './FileService'; -import NoteService from './NoteService'; +import { DEFAULT_STORAGE_URLS, DEFAULT_VALIDATOR_ID } from '@Front/Config/AppConstants'; export default class FolderService extends AbstractService { @@ -17,7 +11,7 @@ export default class FolderService extends AbstractService { super(); } - public static createFolder(folderData: any, stakeholdersId: string[], customersId: string[]): Promise { + public static async createFolder(folderData: any, customersId: string[]): Promise<{ processId: string, processData: any }> { const ownerId: string = User.getInstance().getPairingId()!; const processData: any = { @@ -30,9 +24,7 @@ export default class FolderService extends AbstractService { }; const privateFields: string[] = Object.keys(processData); - privateFields.splice(privateFields.indexOf('uid'), 1); - privateFields.splice(privateFields.indexOf('utype'), 1); - privateFields.splice(privateFields.indexOf('isDeleted'), 1); + const allFields: string[] = [...privateFields, 'roles']; const roles: any = { demiurge: { @@ -40,135 +32,101 @@ export default class FolderService extends AbstractService { validation_rules: [], storages: [] }, - owner: { - members: [ownerId], + owners: { + members: [ownerId, DEFAULT_VALIDATOR_ID], validation_rules: [ { - quorum: 0.5, - fields: [...privateFields, 'roles', 'uid', 'utype'], - min_sig_member: 1, + quorum: 0.01, + fields: allFields, + min_sig_member: 0.01, }, ], - storages: [] + storages: [...DEFAULT_STORAGE_URLS] }, - stakeholders: { - members: stakeholdersId, - validation_rules: [ - { - quorum: 0.5, - fields: ['documents', 'motes'], - min_sig_member: 1, - }, - ], - storages: [] + guests: { + members: [], + validation_rules: [{ + quorum: 0.01, + fields: allFields, + min_sig_member: 0.01, + }], + storages: [...DEFAULT_STORAGE_URLS] }, customers: { members: customersId, validation_rules: [ { quorum: 0.0, - fields: privateFields, + fields: allFields, min_sig_member: 0.0, }, ], - storages: [] + storages: [...DEFAULT_STORAGE_URLS] }, apophis: { - members: [ownerId], + members: [ownerId, DEFAULT_VALIDATOR_ID], validation_rules: [], storages: [] } }; - return new Promise((resolve: (processCreated: any) => void, reject: (error: string) => void) => { - this.messageBus.createProcess(processData, privateFields, roles).then((processCreated: any) => { - this.messageBus.notifyUpdate(processCreated.processId, processCreated.process.states[0].state_id).then(() => { - this.messageBus.validateState(processCreated.processId, processCreated.process.states[0].state_id).then((_stateValidated: any) => { - this.getFolderByUid(processCreated.processData.uid).then(resolve).catch(reject); - }).catch(reject); - }).catch(reject); - }).catch(reject); - }); + try { + const processCreated = await this.messageBus.createProcess(processData, privateFields, roles); + await this.messageBus.notifyUpdate(processCreated.processId, processCreated.process.states[0].state_id); + await this.messageBus.validateState(processCreated.processId, processCreated.process.states[0].state_id); + const finalProcessData = await this.messageBus.getProcessData(processCreated.processId); + + return { processId: processCreated.processId, processData: finalProcessData }; + } catch (error) { + throw error; + } } - public static getFolders(callback: (processes: any[]) => void, waitForAll: boolean = false): void { + public static getFolders(callback: (processes: Record) => void): void { // Check if we have valid cache - const items: any[] = this.getItems('_folders_'); - if (items.length > 0 && !waitForAll) { - setTimeout(() => callback([...items]), 0); + const items: Record = this.getItems('_folders_'); + if (Object.keys(items).length > 0) { + setTimeout(() => callback(items), 0); } - this.messageBus.getProcessesDecoded((publicValues: any) => - publicValues['uid'] && - publicValues['utype'] && - publicValues['utype'] === 'folder' && - publicValues['isDeleted'] && - publicValues['isDeleted'] === 'false' && - !items.map((item: any) => item.processData.uid).includes(publicValues['uid']) - ).then(async (processes: any[]) => { - if (processes.length === 0) { - if (waitForAll) { - callback([...items]); - } + this.messageBus.getProcessesDecoded((_processId: string, values: any) => { + return values['utype'] + && values['utype'] === 'folder' + && values['isDeleted'] + && values['isDeleted'] === 'false'; + }).then(async (processes: Record) => { + if (Object.keys(processes).length === 0) { + callback(items); return; } - const updatedItems: any[] = [...items]; + console.log('[FolderService/getFolders] processes', processes); - for (let processIndex = 0; processIndex < processes.length; processIndex++) { - let process = processes[processIndex]; - - if (!waitForAll) { - process = await this.completeFolder(process, (processInProgress: any) => { - const currentItems: any[] = [...updatedItems]; - - const existingIndex: number = currentItems.findIndex(item => item.processData?.uid === processInProgress.processData?.uid); - if (existingIndex >= 0) { - currentItems[existingIndex] = processInProgress; - } else { - currentItems.push(processInProgress); - } - - callback(currentItems); - }); - } else { - process = await this.completeFolder(process); - } + const updatedItems: Record = { ...items }; + for (const [processId, process] of Object.entries(processes)) { // Update cache - this.setItem('_folders_', process); + this.setItem('_folders_', processId, process); - const existingIndex: number = updatedItems.findIndex(item => item.processData?.uid === process.processData?.uid); - if (existingIndex >= 0) { - updatedItems[existingIndex] = process; - } else { - updatedItems.push(process); - } - - if (!waitForAll) { - callback([...updatedItems]); - } + updatedItems[processId] = process; } - if (waitForAll) { - callback([...updatedItems]); - } + callback(updatedItems); }); } - public static getFoldersBy(whereClause: { [path: string]: any }): Promise { - return new Promise((resolve: (folders: any[]) => void) => { - this.getFolders((processes: any[]) => { - if (processes.length === 0) { - resolve([]); + public static getFoldersBy(whereClause: { [path: string]: any }): Promise> { + return new Promise>((resolve: (folders: Record) => void) => { + this.getFolders((processes: Record) => { + if (Object.keys(processes).length === 0) { + resolve({}); } else { - resolve(processes.filter((process: any) => { - const folder: any = process.processData; - + const filteredEntries = Object.entries(processes).filter(([processId, process]) => { for (const path in whereClause) { const paths: string[] = path.split('.'); - let value: any = folder; + let value: any = process; + value['processId'] = processId; for (let i = 0; i < paths.length; i++) { const currentPath = paths[i]; if (!currentPath || value === undefined || value === null) { @@ -183,146 +141,40 @@ export default class FolderService extends AbstractService { } return true; - })); + }); + + // Convert filtered entries back to a Record + const filteredProcesses: Record = {}; + filteredEntries.forEach(([processId, process]) => { + filteredProcesses[processId] = process; + }); + + resolve(filteredProcesses); } - }, true); - }); - } - - public static getFolderByUid(uid: string): Promise { - // Check if we have valid cache - const item: any = this.getItem('_folders_', uid); - if (item) { - return Promise.resolve(item); - } - - return new Promise((resolve: (process: any) => void, reject: (error: string) => void) => { - this.messageBus.getProcessesDecoded((publicValues: any) => - publicValues['uid'] && - publicValues['uid'] === uid && - publicValues['utype'] && - publicValues['utype'] === 'folder' && - publicValues['isDeleted'] && - publicValues['isDeleted'] === 'false' - ).then(async (processes: any[]) => { - if (processes.length === 0) { - resolve(null); - } else { - let process: any = processes[0]; - process = await this.completeFolder(process); - - // Update cache - this.setItem('_folders_', process); - - resolve(process); - } - }).catch(reject); - }); - } - - public static updateFolder(process: any, newData: any): Promise { - return new Promise((resolve: () => void, reject: (error: string) => void) => { - this.messageBus.updateProcess(process.processId, { updated_at: new Date().toISOString(), ...newData }, [], null).then((processUpdated: any) => { - const newStateId: string = processUpdated.diffs[0]?.state_id; - this.messageBus.notifyUpdate(process.processId, newStateId).then(() => { - this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => { - const folderUid: string = process.processData.uid; - this.removeItem('_folders_', folderUid); - - this.getFolderByUid(folderUid).then(resolve).catch(reject); - }).catch(reject); - }).catch(reject); - }).catch(reject); - }); - } - - public static refreshFolderByUid(uid: string): Promise { - return new Promise((resolve: () => void, reject: (error: string) => void) => { - this.getFolderByUid(uid).then((process: any) => { - this.updateFolder(process, {}).then(resolve).catch(reject); - }).catch(reject); - }); - } - - private static async completeFolder(process: any, progressCallback?: (processInProgress: any) => void): Promise { - const progressiveProcess: any = JSON.parse(JSON.stringify(process)); - - if (process.processData.customers && process.processData.customers.length > 0) { - process.processData.customers = await new Promise(async (resolve: (customers: any[]) => void) => { - const customers: any[] = []; - for (const customer of process.processData.customers) { - customers.push((await CustomerService.getCustomerByUid(customer.uid)).processData); - } - resolve(customers); }); + }); + } - if (process.processData.customers && process.processData.customers.length > 0) { - const documents: any[] = (await DocumentService.getDocuments()).map((process: any) => process.processData); - for (const customer of process.processData.customers) { - customer.documents = documents.filter((document: any) => (document.depositor && document.depositor.uid === customer.uid) || (document.customer && document.customer.uid === customer.uid)); + public static async updateFolder(processId: string, newData: any): Promise { + try { + const processUpdated = await this.messageBus.updateProcess( + processId, + { updated_at: new Date().toISOString(), ...newData }, + [], + null + ); + + const newStateId: string = processUpdated.diffs[0]?.state_id; + await this.messageBus.notifyUpdate(processId, newStateId); + await this.messageBus.validateState(processId, newStateId); - for (const document of customer.documents) { - if (document.document_type) { - document.document_type = (await DocumentTypeService.getDocumentTypeByUid(document.document_type.uid)).processData; - } - - if (document.files && document.files.length > 0) { - const files: any[] = []; - for (const file of document.files) { - files.push({ uid: file.uid, file_name: (await FileService.getFileByUid(file.uid)).processData.file_name }); - } - document.files = files; - } - } - } - } - - if (progressCallback) { - progressiveProcess.processData.customers = process.processData.customers; - progressCallback(JSON.parse(JSON.stringify(progressiveProcess))); - } + const processData = await this.messageBus.getProcessData(processId); + + // Update cache + this.setItem('_folders_', processId, processData); + } catch (error) { + console.error('Failed to update folder:', error); + throw error; // Re-throw to allow caller to handle } - - if (process.processData.stakeholders && process.processData.stakeholders.length > 0) { - process.processData.stakeholders = await new Promise(async (resolve: (stakeholders: any[]) => void) => { - const stakeholders: any[] = []; - for (const stakeholder of process.processData.stakeholders) { - stakeholders.push((await CollaboratorService.getCollaboratorByUid(stakeholder.uid)).processData); - } - resolve(stakeholders); - }); - - if (progressCallback) { - progressiveProcess.processData.stakeholders = process.processData.stakeholders; - progressCallback(JSON.parse(JSON.stringify(progressiveProcess))); - } - } - - if (process.processData.deed && process.processData.deed.deed_type) { - const deed_type: any = (await DeedTypeService.getDeedTypeByUid(process.processData.deed.deed_type.uid)).processData; - process.processData.deed.deed_type = deed_type; - - if (deed_type.document_types && deed_type.document_types.length > 0) { - // Remove duplicates - process.processData.deed.document_types = deed_type.document_types.filter((item: any, index: number) => deed_type.document_types.findIndex((t: any) => t.uid === item.uid) === index); - } - - if (progressCallback) { - progressiveProcess.processData.deed = process.processData.deed; - progressCallback(JSON.parse(JSON.stringify(progressiveProcess))); - } - } - - const notes: any[] = (await NoteService.getNotes()).map((process: any) => process.processData); - if (notes.length > 0) { - process.processData.notes = notes.filter((note: any) => note.folder.uid === process.processData.uid); - - if (progressCallback) { - progressiveProcess.processData.notes = process.processData.notes; - progressCallback(JSON.parse(JSON.stringify(progressiveProcess))); - } - } - - return process; } } diff --git a/src/front/Api/Auth/IdNot/index.ts b/src/front/Api/Auth/IdNot/index.ts index c88dc77f..a4c3ae7b 100644 --- a/src/front/Api/Auth/IdNot/index.ts +++ b/src/front/Api/Auth/IdNot/index.ts @@ -108,7 +108,7 @@ export default class Auth extends BaseApiService { } } - public async getOfficeProcessByIdNot(): Promise { + public async getOfficeProcessByIdNot(): Promise<{ success: boolean; data: { processId: string, processData: { [key: string]: any } } }> { const baseBackUrl = 'http://localhost:8080';//variables.BACK_API_PROTOCOL + variables.BACK_API_HOST; const url = new URL(`${baseBackUrl}/api/v1/process/office`); diff --git a/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx b/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx index 5255a395..85f0ca62 100644 --- a/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx +++ b/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx @@ -7,7 +7,6 @@ import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import DefaultDeedTypesDashboard from "@Front/Components/LayoutTemplates/DefaultDeedTypeDashboard"; import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import Module from "@Front/Config/Module"; -import { DeedType, Office } from "le-coffre-resources/dist/Admin"; import { useRouter } from "next/router"; import { useCallback, useState } from "react"; @@ -19,6 +18,7 @@ import UserStore from "@Front/Stores/UserStore"; import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; import DeedTypeService from "src/common/Api/LeCoffreApi/sdk/DeedTypeService"; import { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants"; +import Auth from "@Front/Api/Auth/IdNot"; type IProps = {}; export default function DeedTypesCreate(props: IProps) { @@ -31,27 +31,44 @@ export default function DeedTypesCreate(props: IProps) { async (e: React.FormEvent | null, values: { [key: string]: string }) => { try { const user: any = UserStore.instance.getUser(); - const officeId: string = user.office.uid; - - const deedType = DeedType.hydrate({ - name: values["name"], - description: values["description"], - office: Office.hydrate({ - uid: officeId, - }), - }); - try { - await validateOrReject(deedType, { groups: ["createDeedType"], forbidUnknownValues: true }); - } catch (validationErrors: Array | any) { - setValidationError(validationErrors as ValidationError[]); + if (!user) { + console.error("DeedTypesCreate: User not found - user is null or undefined"); return; } + const res = await Auth.getInstance().getOfficeProcessByIdNot(); + if (!res.success) { + console.error("DeedTypesCreate: Office not found - office is null or undefined"); + return; + } + const officeId: string | undefined = res.data.processId; + const officeIdNot: string | undefined = res.data.processData['idNot']; + if (!officeId || !officeIdNot) { + console.error("DeedTypesCreate: officeId or officeIdNot is undefined - office.processData.idNot is missing"); + return; + } + + // TODO: We should update the type definition to be able to use validation again + // const deedType = DeedType.hydrate({ + // name: values["name"], + // description: values["description"], + // office: Office.hydrate({ + // idNot: officeId, + // }), + // }); + // try { + // await validateOrReject(deedType, { groups: ["createDeedType"], forbidUnknownValues: true }); + // } catch (validationErrors: Array | any) { + // console.log("validationErrors", validationErrors); + // setValidationError(Array.isArray(validationErrors) ? validationErrors : []); + // return; + // } const deedTypeData: any = { name: values["name"], description: values["description"], office: { uid: officeId, + idNot: officeIdNot, } }; @@ -61,15 +78,18 @@ export default function DeedTypesCreate(props: IProps) { title: "Succès !", description: "Type d'acte créé avec succès" }); + const deedTypeUid = processCreated.processId; + // Remove ':0' suffix from processId for URL navigation + const urlId = deedTypeUid.replace(/:0$/, ''); router.push( Module.getInstance() .get() - .modules.pages.DeedTypes.pages.DeedTypesInformations.props.path.replace("[uid]", processCreated.processData.uid), + .modules.pages.DeedTypes.pages.DeedTypesInformations.props.path.replace("[uid]", urlId), ); LoaderService.getInstance().hide(); }); } catch (validationErrors: Array | any) { - setValidationError(validationErrors as ValidationError[]); + setValidationError(Array.isArray(validationErrors) ? validationErrors : []); return; } }, @@ -106,12 +126,12 @@ export default function DeedTypesCreate(props: IProps) { error.property === "name")} + validationError={Array.isArray(validationError) ? validationError.find((error) => error.property === "name") : undefined} /> error.property === "description")} + validationError={Array.isArray(validationError) ? validationError.find((error) => error.property === "description") : undefined} />
@@ -126,7 +128,7 @@ export default function ClientView(props: IProps) {
- {customer.uid && folder.uid && } + {customer?.uid && folder.processId && } ); diff --git a/src/front/Components/Layouts/Folder/index.tsx b/src/front/Components/Layouts/Folder/index.tsx index 4bf850c6..0879e8f1 100644 --- a/src/front/Components/Layouts/Folder/index.tsx +++ b/src/front/Components/Layouts/Folder/index.tsx @@ -25,40 +25,36 @@ export default function Folder() { useEffect(() => { // TODO: review - FolderService.getFoldersBy({ status: EFolderStatus.LIVE }).then((processes: any[]) => { - if (processes.length > 0) { - let folders: any[] = processes.map((process: any) => process.processData); + FolderService.getFoldersBy({ status: EFolderStatus.LIVE }).then((processes: Record) => { + if (Object.keys(processes).length > 0) { + let folders: any[] = Object.entries(processes).map(([processId, process]) => { + const res = { + ...process, + processId: processId + }; + return res; + }); // OrderBy created_at desc folders = folders.sort((a: any, b: any) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); if (folders.length > 0) { + const folderUid = folders[0]?.processId; + + if (!folderUid) { + return; + } + router.push( Module.getInstance() .get() - .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folders[0].uid) + .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid as string) ); } + } else { + console.debug('[Folder] No folders found'); } }); - - /* - Folders.getInstance() - .get({ - q: { - where: { status: EFolderStatus.LIVE }, - orderBy: { created_at: "desc" }, - }, - }) - .then((folders) => { - if (folders.length > 0) - router.push( - Module.getInstance() - .get() - .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folders[0]?.uid ?? ""), - ); - }); - */ }, [router]); return ( diff --git a/src/front/Components/Layouts/LoginCallback/index.tsx b/src/front/Components/Layouts/LoginCallback/index.tsx index dcd31de4..fff5c755 100644 --- a/src/front/Components/Layouts/LoginCallback/index.tsx +++ b/src/front/Components/Layouts/LoginCallback/index.tsx @@ -7,6 +7,7 @@ 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"; @@ -21,16 +22,10 @@ import MessageBus from "src/sdk/MessageBus"; import Iframe from "src/sdk/Iframe"; import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; -import ImportData, { ProgressInfo } from "src/common/Api/LeCoffreApi/sdk/ImportData"; -import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService"; -import OfficeService from "src/common/Api/LeCoffreApi/sdk/OfficeService"; -import OfficeRoleService from "src/common/Api/LeCoffreApi/sdk/OfficeRoleService"; -import CollaboratorService from "src/common/Api/LeCoffreApi/sdk/CollaboratorService"; -import { DEFAULT_STORAGE_URLS, DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants"; +import { ProgressInfo } from "src/common/Api/LeCoffreApi/sdk/ImportData"; export default function LoginCallBack() { const router = useRouter(); - const [idNotUser, setIdNotUser] = useState(null); const [isAuthModalOpen, setIsAuthModalOpen] = useState(false); const [isConnected, setIsConnected] = useState(false); @@ -43,169 +38,26 @@ export default function LoginCallBack() { description: '' }); - const getOffice = async (idNotUser: any) => { - return await new Promise((resolve: (office: any) => void) => { - OfficeService.getOffices().then((processes: any[]) => { - const officeFound: any = processes.length > 0 ? processes.find((office: any) => office.processData.idNot === idNotUser.office.idNot) : null; - if (officeFound) { - resolve(officeFound); - } else { - // Some info must be here or have some value, just to be sure - if (!idNotUser.office.office_status || idNotUser.office.office_status !== 'ACTIVATED') { - console.error(`[LoginCallback] office_status is not ACTIVATED for idNot ${idNotUser.office.idNot}`); - return; - } - - // I guess if we don't have crpcen that's also a big problem - if (!idNotUser.office.crpcen) { - console.error(`[LoginCallback] crpcen is not set for idNot ${idNotUser.office.idNot}`); - return; - } - - // We create office - const officeData: any = { - idNot: idNotUser.office.idNot, - name: idNotUser.office.name, - crpcen: idNotUser.office.crpcen, - address: { - create: { - address: idNotUser.office.address.address, - zip_code: idNotUser.office.address.zip_code, - city: idNotUser.office.address.city - } - }, - office_status: idNotUser.office.office_status // must be ACTIVATED though - }; - - Auth.getInstance().getIdNotUserForOffice(idNotUser.office.idNot).then((users: any) => { - console.log('users : ', users); - const activeUsers = users.result.filter((user: any) => user.activite === 'En exercice'); - let officeCollaborators: any[] = []; - for (const user of activeUsers) { - CollaboratorService.getCollaboratorByUid(user.uid).then((collaborator: any) => { - console.log('collaborator : ', collaborator); - officeCollaborators.push(collaborator); - }); - } - - OfficeService.createOffice(officeData, officeCollaborators, DEFAULT_VALIDATOR_ID, [...DEFAULT_STORAGE_URLS]).then((process: any) => { - if (process) { - const office: any = process.processData; - resolve(office); - } - }); - }); - } + const waitForUserInfo = (): Promise => { + return new Promise((resolve, reject) => { + if (UserStore.instance.getUser()) { + resolve(UserStore.instance.getUser()); return; - }); - }); - }; - - const getCollaborator = async (idNotUser: any) => { - return await new Promise(async (resolve: (role: any) => void) => { - const processFound: any | null = await CollaboratorService.getCollaboratorBy({ idNot: idNotUser.idNot }); - if (processFound) { - console.log('Found a collaborator for idNot', idNotUser.idNot); - // TODO: check if the collaborator is in the office process - const office: any = await getOffice(idNotUser); - // Take the role of the collaborator - MessageBus.getInstance().getRolesForProcess(processFound.processId).then((roles: any) => { - console.log('roles : ', roles); - // We should find one pairing id in the role 'owner' - const owners = roles['owner'].members; - if (owners.length !== 1) { - console.error('[LoginCallback] owner should have 1 member'); - return; - } - const ownerPairingId = owners[0]; - // Now we can check if the owner pairing id is in the office roles - MessageBus.getInstance().getRolesForProcess(office.processId).then((officeRoles: any) => { - const officeOwners = officeRoles['owner'].members; - if (!officeOwners.includes(ownerPairingId)) { - // We add the newly created collaborator to the office roles - OfficeService.addCollaborators(office, officeRoles, [ownerPairingId]).then((process: any) => { - resolve(processFound); - }); - } else { - // Nothing to do - resolve(processFound); - } - }); - }); - } else { - console.log('No collaborator found for idNot', idNotUser.idNot); - const office: any = await getOffice(idNotUser); - - const role: any = (await RoleService.getRoles()) - .map((process: any) => process.processData) - .find((role: any) => role.name === idNotUser.role.name); - - const officeRole: any = (await OfficeRoleService.getOfficeRoles()) - .map((process: any) => process.processData) - .filter((officeRole: any) => officeRole.office.uid === office.processData.uid) - .find((officeRole: any) => officeRole.name === idNotUser.office_role.name); - - if (!office || !role || !officeRole) { - LoaderService.getInstance().hide(); - setShowProgress(true); - - await ImportData.import(office, DEFAULT_VALIDATOR_ID, (info: ProgressInfo) => { - setProgressInfo(info); - }); - - setShowProgress(false); - LoaderService.getInstance().show(); - } - - const collaboratorData: any = { - idNot: idNotUser.idNot, - contact: idNotUser.contact, - office: { - uid: office.uid - }, - role: { - uid: role.uid - }, - office_role: { - uid: officeRole.uid - } - }; - - CollaboratorService.createCollaborator(collaboratorData, DEFAULT_VALIDATOR_ID).then((newCollaborator: any) => { - if (newCollaborator) { - // Now that we created the collaborator, we must check that it's in the office roles (probably not) - MessageBus.getInstance().getRolesForProcess(newCollaborator.processId).then((roles: any) => { - console.log('roles : ', roles); - // We should have our own pairing id in roles['owner'] - const owner = roles['owner'].members; - if (owner.length !== 1) { - console.error('[LoginCallback] owner should have 1 member'); - return; - } - const ownerPairingId = owner[0]; - if (ownerPairingId !== newCollaborator.processData.uid) { - console.error('[LoginCallback] owner pairing id is not the same as the collaborator uid'); - return; - } - - // is ownerPairingId in roles for the office process? - MessageBus.getInstance().getRolesForProcess(office.processId).then((officeRoles: any) => { - const officeOwners = officeRoles['owner'].members; - if (!officeOwners.includes(ownerPairingId)) { - // We add the newly created collaborator to the office roles - OfficeService.addCollaborators(office, officeRoles, [ownerPairingId]).then((process: any) => { - resolve(newCollaborator); - }); - } else { - // Nothing to do - resolve(newCollaborator); - } - }); - - }); - } - }); } + + // 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); }); }; @@ -216,8 +68,8 @@ export default function LoginCallBack() { // 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.4nkweb.com')) { - window.location.href = window.location.href.replace('http://local.4nkweb.com:3000/authorized-client', '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; } @@ -230,22 +82,34 @@ export default function LoginCallBack() { window.history.replaceState({}, document.title, rootUrl); } - const user: any = await Auth.getInstance().getIdNotUser(code as string); - setIdNotUser(user.idNotUser); - setIsAuthModalOpen(true); - console.log('[LoginCallback] idNotUser', idNotUser); - /* - const token: any = null; - if (!token) return router.push(Module.getInstance().get().modules.pages.Login.props.path); - await UserStore.instance.connect(token.accessToken, token.refreshToken); - const jwt = JwtService.getInstance().decodeJwt(); - if (!jwt) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); - if (jwt.rules && !jwt.rules.includes("GET folders")) { - return router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path); + 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); - //return router.push(Module.getInstance().get().modules.pages.Folder.props.path); - */ + console.log('[LoginCallback] authToken stored successfully'); + return; } catch (e: any) { if (e.http_status === 401 && e.message === "Email not found") { @@ -257,21 +121,6 @@ export default function LoginCallBack() { return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); } } - /* - const refreshToken = CookieService.getInstance().getCookie("leCoffreRefreshToken"); - if (!refreshToken) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); - const isTokenRefreshed = await JwtService.getInstance().refreshToken(refreshToken); - const jwt = JwtService.getInstance().decodeJwt(); - if (!jwt) return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1"); - if (!jwt.rules.includes("GET folders")) { - return router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path); - } - if (isTokenRefreshed) { - //setIsAuthModalOpen(true); - //return router.push(Module.getInstance().get().modules.pages.Folder.props.path); - return; - } - */ return router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=2"); } getUser(); @@ -354,23 +203,110 @@ export default function LoginCallBack() { LoaderService.getInstance().show(); MessageBus.getInstance().initMessageListener(); MessageBus.getInstance().isReady().then(async () => { - const collaborator: any = await getCollaborator(idNotUser); - if (!UserStore.instance.connect(collaborator)) { - console.error('[LoginCallback] collaborator not connected'); + 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"); - return; + } finally { + MessageBus.getInstance().destroyMessageListener(); + LoaderService.getInstance().hide(); } - - MessageBus.getInstance().destroyMessageListener(); - LoaderService.getInstance().hide(); - - /* - if (jwt.rules && !jwt.rules.includes("GET folders")) { - router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path); - } - */ - - window.location.href = Module.getInstance().get().modules.pages.Folder.props.path; + return; }); }, 100); }}