import User from "./User"; import System, {UserKey} from "./System"; import LocationRepo, { LocationByTagResult, LocationElementQueryResult, LocationQueryResult } from "../repositories/location.repo"; export interface SubElement { id: string; name: string; description: string; } export interface Element { id: string; name: string; description: string; subElements: SubElement[]; } export interface LocationProps { id: string; name: string; elements: Element[]; } export default class Location { /** * Récupère toutes les locations pour un utilisateur et un livre donnés. * @param {string} userId - L'ID de l'utilisateur. * @param {string} bookId - L'ID du livre. * @returns {Promise} - Une promesse qui résout un tableau de propriétés de location. * @throws {Error} - Lance une erreur si une exception se produit lors de la récupération des locations. */ static async getAllLocations(userId: string, bookId: string): Promise { const locations: LocationQueryResult[] = await LocationRepo.getLocation(userId, bookId); if (!locations || locations.length === 0) return []; const user = new User(userId); const userKeys: UserKey[] = await System.getAllUserKeysAndVersions(userId); const locationArray: LocationProps[] = []; for (const record of locations) { let location = locationArray.find(loc => loc.id === record.loc_id); if (!location) { const key: string = await user.getUserKey(record.loc_meta, true, userKeys); const decryptedName: string = System.decryptDataWithUserKey(record.loc_name, key)/* ton code de décryptage ici avec record.loc_name */; location = { id: record.loc_id, name: decryptedName, elements: [] }; locationArray.push(location); } if (record.element_id) { let element = location.elements.find(elem => elem.id === record.element_id); if (!element) { const key: string = await user.getUserKey(record.element_meta, true, userKeys); const decryptedName: string = System.decryptDataWithUserKey(record.element_name, key)/* ton code de décryptage ici avec record.element_name */; const decryptedDesc: string = record.element_description ? System.decryptDataWithUserKey(record.element_description, key) : ''/* ton code de décryptage ici avec record.element_description */; element = { id: record.element_id, name: decryptedName, description: decryptedDesc, subElements: [] }; location.elements.push(element); } if (record.sub_element_id) { const subElementExists = element.subElements.some(sub => sub.id === record.sub_element_id); if (!subElementExists) { const key: string = await user.getUserKey(record.sub_elem_meta, true, userKeys); const decryptedName: string = System.decryptDataWithUserKey(record.sub_elem_name, key)/* ton code de décryptage ici avec record.sub_elem_name */; const decryptedDesc: string = record.sub_elem_description ? System.decryptDataWithUserKey(record.sub_elem_description, key) : ''/* ton code de décryptage ici avec record.sub_elem_description */; element.subElements.push({ id: record.sub_element_id, name: decryptedName, description: decryptedDesc }); } } } } return locationArray; } static async addLocationSection(userId: string, locationName: string, bookId: string): Promise { const user = new User(userId); const meta: string = System.encryptDateKey(userId); const userKey: string = await user.getUserKey(meta, true); const originalName: string = System.hashElement(locationName); const encryptedName: string = System.encryptDataWithUserKey(locationName, userKey); const locationId: string = System.createUniqueId(); return await LocationRepo.insertLocation(userId, locationId, bookId, encryptedName, originalName, meta); } static async addLocationElement(userId: string, locationId: string, elementName: string) { const user = new User(userId); const meta: string = System.encryptDateKey(userId); const userKey: string = await user.getUserKey(meta, true); const originalName: string = System.hashElement(elementName); const encryptedName: string = System.encryptDataWithUserKey(elementName, userKey); const elementId: string = System.createUniqueId(); return LocationRepo.insertLocationElement(userId, elementId, locationId, encryptedName, originalName, meta) } static async addLocationSubElement(userId: string, elementId: string, subElementName: string) { const user = new User(userId); const meta: string = System.encryptDateKey(userId); const userKey: string = await user.getUserKey(meta, true); const originalName: string = System.hashElement(subElementName); const encryptedName: string = System.encryptDataWithUserKey(subElementName, userKey); const subElementId: string = System.createUniqueId(); return LocationRepo.insertLocationSubElement(userId, subElementId, elementId, encryptedName, originalName, meta) } static async updateLocationSection(userId: string, locations: LocationProps[]) { const user = new User(userId); const meta: string = System.encryptDateKey(userId); const userKey: string = await user.getUserKey(meta, true); for (const location of locations) { const originalName: string = System.hashElement(location.name); const encryptedName: string = System.encryptDataWithUserKey(location.name, userKey); await LocationRepo.updateLocationSection(userId, location.id, encryptedName, originalName, meta) for (const element of location.elements) { const originalName: string = System.hashElement(element.name); const encryptedName: string = System.encryptDataWithUserKey(element.name, userKey); const encryptDescription: string = element.description ? System.encryptDataWithUserKey(element.description, userKey) : ''; await LocationRepo.updateLocationElement(userId, element.id, encryptedName, originalName, encryptDescription, meta) for (const subElement of element.subElements) { const originalName: string = System.hashElement(subElement.name); const encryptedName: string = System.encryptDataWithUserKey(subElement.name, userKey); const encryptDescription: string = subElement.description ? System.encryptDataWithUserKey(subElement.description, userKey) : ''; await LocationRepo.updateLocationSubElement(userId, subElement.id, encryptedName, originalName, encryptDescription, meta) } } } return { valid: true, message: 'Les sections ont été mis à jour.' } } static async deleteLocationSection(userId: string, locationId: string) { return LocationRepo.deleteLocationSection(userId, locationId); } static async deleteLocationElement(userId: string, elementId: string) { return LocationRepo.deleteLocationElement(userId, elementId); } static async deleteLocationSubElement(userId: string, subElementId: string) { return LocationRepo.deleteLocationSubElement(userId, subElementId); } static async getLocationTags(userId: string, bookId: string): Promise { const data: LocationElementQueryResult[] = await LocationRepo.fetchLocationTags(userId, bookId); if (!data || data.length === 0) return []; const user = new User(userId); const userKeys: UserKey[] = await System.getAllUserKeysAndVersions(userId); const elementCounts = new Map(); data.forEach((record: LocationElementQueryResult): void => { elementCounts.set(record.element_id, (elementCounts.get(record.element_id) || 0) + 1); }); const subElements: SubElement[] = []; const processedIds = new Set(); for (const record of data) { const elementCount: number = elementCounts.get(record.element_id) || 0; if (elementCount > 1 && record.sub_element_id) { if (processedIds.has(record.sub_element_id)) continue; const key: string = await user.getUserKey(record.sub_elem_meta, true, userKeys); subElements.push({ id: record.sub_element_id, name: System.decryptDataWithUserKey(record.sub_elem_name, key), description: record.sub_elem_description ? System.decryptDataWithUserKey(record.sub_elem_description, key) : '' }); processedIds.add(record.sub_element_id); } else if (elementCount === 1 && !record.sub_element_id) { if (processedIds.has(record.element_id)) continue; const key: string = await user.getUserKey(record.element_meta, true, userKeys); subElements.push({ id: record.element_id, name: System.decryptDataWithUserKey(record.element_name, key), description: record.element_description ? System.decryptDataWithUserKey(record.element_description, key) : '' }); processedIds.add(record.element_id); } } return subElements; } static async getLocationsByTags(userId: string, locations: string[]): Promise { const locationsTags: LocationByTagResult[] = await LocationRepo.fetchLocationsByTags(userId, locations); if (!locationsTags || locationsTags.length === 0) return []; const user = new User(userId); const userKeys: UserKey[] = await System.getAllUserKeysAndVersions(userId); const locationTags: Element[] = []; for (const record of locationsTags) { let element: Element | undefined = locationTags.find((elem: Element): boolean => elem.name === record.element_name); if (!element) { const key: string = await user.getUserKey(record.element_meta, true, userKeys); const decryptedName: string = System.decryptDataWithUserKey(record.element_name, key); const decryptedDesc: string = record.element_description ? System.decryptDataWithUserKey(record.element_description, key) : ''; element = { id: record.element_id, name: decryptedName, description: decryptedDesc, subElements: [] }; locationTags.push(element); } if (record.sub_elem_name) { const subElementExists: boolean = element.subElements.some(sub => sub.name === record.sub_elem_name); if (!subElementExists) { const key: string = await user.getUserKey(record.sub_elem_meta, true, userKeys); const decryptedName: string = System.decryptDataWithUserKey(record.sub_elem_name, key); const decryptedDesc: string = record.sub_elem_description ? System.decryptDataWithUserKey(record.sub_elem_description, key) : ''; element.subElements.push({ id: '', name: decryptedName, description: decryptedDesc }); } } } return locationTags; } static async locationsDescription(locations: Element[]): Promise { return locations.map((location: Element): string => { const fields: string[] = []; if (location.name) fields.push(`Nom : ${location.name}`); if (location.description) fields.push(`Description : ${location.description}`); return fields.join('\n'); }).join('\n\n'); } }