oro-sdk 5.3.2 → 5.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- {"version":3,"file":"oro-sdk.cjs.production.min.js","sources":["../src/helpers/client.ts","../src/models/error.ts","../src/helpers/workflow.ts","../src/helpers/patient-registration.ts","../src/helpers/vault-grants.ts","../src/sdk-revision/client.ts","../src/client.ts","../src/services/external/clinia.ts","../src/index.ts"],"sourcesContent":["import {\n PopulatedWorkflowData,\n MetadataCategory,\n SelectedAnswersData,\n} from 'oro-sdk-apis'\nimport { PersonalInformations } from '../models/client'\n\nconst personalMetaToPrefix = {\n [MetadataCategory.Personal]: 'you',\n [MetadataCategory.ChildPersonal]: 'child',\n [MetadataCategory.OtherPersonal]: 'other',\n}\n\n/**\n * This function extract PersonalInformations from data input object coming from workflow\n * @param data extracted from WorkflowData\n * @returns PersonalInformations of a patient\n */\nexport function identificationToPersonalInformations(\n data: any,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n): PersonalInformations {\n const prefix = personalMetaToPrefix[category]\n\n return {\n birthday: data[`${prefix}Birthday`],\n firstname: data[`${prefix}Firstname`],\n gender: data[`${prefix}Gender`],\n name: data[`${prefix}Name`],\n phone: data[`${prefix}Phone`],\n zip: data[`${prefix}Zip`],\n hid: data[`${prefix}HID`] ?? data[`${prefix}ID`], // This is done for backward compatibility (historically youID was used)\n pharmacy: data[`${prefix}Pharmacy`],\n address: data[`${prefix}Address`],\n }\n}\n\nexport function toActualObject(data: PopulatedWorkflowData) {\n const ret: any = {}\n\n Object.entries(data.fields).forEach(([key, field]) => {\n ret[key] = field.displayedAnswer ? field.displayedAnswer : field.answer\n })\n\n return ret\n}\n\n/**\n * This function update a PopulatedWorkflowData with PersonalInformations\n * @param infos the personal informations\n * @param data the PopulatedWorkflowData\n * @returns an updated PopulatedWorkflowData\n */\nexport function updatePersonalIntoPopulatedWorkflowData(\n infos: PersonalInformations,\n data: PopulatedWorkflowData,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n) {\n const prefix = personalMetaToPrefix[category]\n\n const ret = JSON.parse(JSON.stringify(data)) // deep copy PopulatedWorkflowData\n\n if (infos.birthday && ret.fields[`${prefix}Birthday`])\n ret.fields[`${prefix}Birthday`].answer = infos.birthday\n if (infos.firstname && ret.fields[`${prefix}Firstname`])\n ret.fields[`${prefix}Firstname`].answer = infos.firstname\n if (infos.gender && ret.fields[`${prefix}Gender`])\n ret.fields[`${prefix}Gender`].answer = infos.gender\n if (infos.name && ret.fields[`${prefix}Name`])\n ret.fields[`${prefix}Name`].answer = infos.name\n if (infos.phone && ret.fields[`${prefix}Phone`])\n ret.fields[`${prefix}Phone`].answer = infos.phone\n if (infos.zip && ret.fields[`${prefix}Zip`])\n ret.fields[`${prefix}Zip`].answer = infos.zip\n if (infos.hid) {\n if (ret.fields[`${prefix}HID`]) {\n ret.fields[`${prefix}HID`].answer = infos.hid\n } else if (ret.fields[`${prefix}ID`]) {\n // This is done for backward compatibility (historically youID was used)\n ret.fields[`${prefix}ID`].answer = infos.hid\n } else {\n // If does not exist create it\n ret.fields[`${prefix}HID`] = { kind: 'text', answer: infos.hid }\n }\n }\n\n return ret\n}\n\n/**\n * This function extract an ISO 3166-1 alpha-2 country and subdivision code from data input object coming from workflow\n * @param answers answers from the WorkflowData\n * @returns an ISO 3166 alpha-2 code or undefined\n */\nexport function extractISOLocalityForConsult(\n answers?: SelectedAnswersData\n): string | undefined {\n if (!answers) {\n return undefined\n }\n\n const arrAnswersWithLocality = answers\n .flatMap((currentAnswerPage) => {\n const arrCountryFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Country') !== -1\n )\n .flat()\n const arrProvinceFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Province') !== -1\n )\n .flat()\n const arrConsultLocalFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Locality') !== -1\n )\n .flat()\n //returning the actual selected values, skipping if their IDs are more complex than a string\n return [\n ...arrCountryFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrProvinceFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrConsultLocalFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ]\n })\n .filter((item) => item !== undefined)\n\n const arrSelectedLocality = arrAnswersWithLocality.filter(\n (currentSelectedLocality) =>\n currentSelectedLocality.startsWith('isoLocalityConsult')\n )\n if (!arrSelectedLocality || arrSelectedLocality.length === 0) {\n console.log('no locality found in ' + arrSelectedLocality)\n return undefined\n }\n //to allow enforcing of an order, we will allow the following pattern in the isoLocalityConsult field name\n // isoLocalityConsult-QC-CA and isoLocalityConsult_1-QC-CA\n // or generally: isoLocalityConsult-<isoValue> or isoLocalityConsult_<priority>-<isoValue>\n const allowedLocalityPatterns = /isoLocalityConsult(?:_(?<indexPriority>\\d*))?-(?<isoValue>[a-zA-Z0-9]{2}-[a-zA-Z0-9]{1,3})/\n const finalLocality = arrSelectedLocality.reduce<string | undefined>(\n (finalLocality, currentSelectedLocality) => {\n const extractedSelected = allowedLocalityPatterns.exec(\n currentSelectedLocality\n )\n const [, indexSelectedPriority, isoSelectedValue] =\n extractedSelected ?? []\n if (!finalLocality) {\n return isoSelectedValue\n }\n\n const extractedFinal = allowedLocalityPatterns.exec(finalLocality)\n const [, indexFinalPriority, isoFinalValue] = extractedFinal ?? []\n //we only keep the old value if there's priority used\n // and the new value is of lower priority\n if (\n !indexSelectedPriority ||\n (indexFinalPriority &&\n indexFinalPriority > indexSelectedPriority)\n ) {\n return isoFinalValue\n }\n\n return isoSelectedValue\n },\n undefined\n )\n\n console.log('Picking locality ' + finalLocality)\n return finalLocality\n}\n\nconst sessionPrivateKeyPrefix = 'sess-pkey'\nexport function sessionStorePrivateKeyName(id: string): string {\n return sessionPrivateKeyPrefix + id\n}\n","export class IncompleteAuthentication extends Error { }\nexport class MissingGrant extends Error { }\nexport class MissingGrantFilter extends Error { }\nexport class MissingLockbox extends Error { }\nexport class MissingLockboxOwner extends Error { }\nexport class AssociatedLockboxNotFound extends Error { }\nexport class WorkflowAnswersMissingError extends Error { }\n","import { getMany } from 'idb-keyval'\nimport { WorkflowAnswersMissingError } from '../models'\nimport {\n MetadataCategory,\n PopulatedWorkflowData,\n PopulatedWorkflowField,\n QuestionData,\n SelectedAnswerData,\n SelectedAnswersData,\n WorkflowData,\n WorkflowPageData,\n WorkflowUploadedImage,\n} from 'oro-sdk-apis'\n\nexport async function filterTriggeredAnsweredWithKind(\n workflowData: WorkflowData,\n kind:\n | 'text'\n | 'text-area'\n | 'text-select-group'\n | 'date'\n | 'number'\n | 'images'\n | 'images-alias'\n | 'body-parts'\n | 'pharmacy-picker'\n | 'online-pharmacy-picker'\n | 'hair-selector-women'\n | 'hair-selector-men'\n | 'hair-loss-stage'\n | 'hair-loss-frontal'\n): Promise<SelectedAnswerData[]> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestionsWithKind = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(\n ([_, question]) => isTriggered(question.triggers || [], flattenedAnswers) && question.kind === kind\n )\n })\n .flat()\n )\n\n const samePageAnswers = workflowData.selectedAnswers.reduce((prev, cur) => {\n return { ...prev, ...cur }\n }, {})\n\n const res = Object.keys(triggeredQuestionsWithKind).map((questionFieldName) => {\n return samePageAnswers[questionFieldName]\n })\n\n return res\n}\n\n/**\n * Filters and Populates the `selectedAnswers` from the workflow by\n * Cross-referencing the `MetaCategory` of the answer's respective question\n * Populates the fields labels and values that are of radio, dropdown and checkbox types\n *\n * @param workflowData\n * @param category\n * @returns An array of record key, value pairs\n */\nexport async function getWorkflowDataByCategory(\n workflowData: WorkflowData,\n category: MetadataCategory\n): Promise<PopulatedWorkflowData> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestions = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(([_, question]) =>\n isTriggered(question.triggers || [], flattenedAnswers)\n )\n })\n .flat()\n )\n\n const fields: Record<string, PopulatedWorkflowField> = {}\n\n // Generates the answers of the specified category and adds the appropriate values if any are missing\n return Promise.all(\n workflowData.selectedAnswers\n .map((e) => Object.entries(e))\n .flat()\n .filter(([k, v]) => triggeredQuestions[k] && triggeredQuestions[k]['metaCategory'] === category)\n .map(([k, v]) => {\n return populateWorkflowField(triggeredQuestions[k], v).then((populatedValue) => {\n fields[k] = populatedValue\n })\n })\n )\n .then(() => {\n const ret: PopulatedWorkflowData = {\n workflowCreatedAt: workflowData.createdAt,\n workflowId: workflowData.id,\n locale: workflowData.locale,\n fields,\n }\n return ret\n })\n .catch((err) => {\n console.error(`Error while extracting ${category} data from workflow`, err)\n throw err\n })\n}\n\nexport async function getImagesFromIndexDb(answer: SelectedAnswerData): Promise<WorkflowUploadedImage[]> {\n return await getMany<WorkflowUploadedImage>((answer as any[]).map((v) => v.id ?? v) as string[])\n}\n\n/**\n * (If applicable) Based on the question kind, and the answer type this function will add and replace the appropriate fields to the\n * field values if they are radio, dropdown and checkbox fields\n *\n *\n * @param question\n * @param answerValue\n * @returns\n */\nasync function populateWorkflowField(\n question: QuestionData,\n answerValue: SelectedAnswerData\n): Promise<PopulatedWorkflowField> {\n let answer: any\n let displayedAnswer: string | string[] | undefined = undefined\n switch (question.kind) {\n case 'text-select-group':\n if (question.answers) {\n displayedAnswer = `${answerValue[0]} ${question.answers[answerValue[1] as string].text}`\n }\n answer = answerValue\n break\n case 'radio':\n case 'radio-card':\n case 'select':\n if (question.answers) {\n displayedAnswer = question.answers[answerValue as string].text\n }\n\n answer = answerValue\n break\n case 'multiple':\n case 'checkbox-group':\n displayedAnswer = (answerValue as string[]).map((value) => {\n if (question.answers) {\n return question.answers[value].text\n }\n\n throw new WorkflowAnswersMissingError()\n })\n\n answer = answerValue\n break\n case 'images':\n answer = await getImagesFromIndexDb(answerValue).then((images) =>\n images.map((image) => {\n const { name, imageData } = image\n\n return { name, imageData }\n })\n )\n break\n default:\n answer = answerValue\n }\n\n return Promise.resolve({\n answer,\n displayedAnswer,\n kind: question.kind,\n })\n}\n\n/**\n * Determine if a question is triggered by some answers\n *\n * We use the following logical combinations of rules:\n *\n * #### Single string\n *\n * ```\n * // Required: rule1\n * rules: rule1\n * ```\n *\n * #### Array of strings (AND is applied between statements):\n *\n * ```\n * // Required: rule1 AND rule2\n * rules: [ rule1, rule2 ]\n * ```\n *\n * #### Array of arrays of strings (OR is applied between inner arrays. AND is applied between inner arrays statements)\n *\n * ```\n * // Required: rule1 OR rule2\n * rules: [\n * [ rule1 ],\n * [ rule2 ]\n * ]\n *\n * // Required: rule1 OR (rule2 AND rule3)\n * rules: [\n * [ rule1 ],\n * [ rule2, rule3 ]\n * ]\n *\n * // THIS IS FORBIDDEN\n * rules: [\n * rule1, // <-- THIS IS FORBIDDEN. Instead use [ rule1 ]\n * [ rule2, rule3 ]\n * ]\n * ```\n *\n * @param triggers the triggering rules\n * @param answers the answers to check againts triggering rules\n * @returns `true` if triggers are verified against ansers. Otherwise, returns `false`.\n * @throws an Error if triggers typing is wrong\n */\nexport function isTriggered(triggers: string[][] | string[] | string, answers: string[]): boolean {\n // is triggers contained in answers\n if (typeof triggers === 'string') {\n return answers.includes(triggers)\n }\n\n if (Array.isArray(triggers)) {\n // rule combination kind: rule1 OR (rule2 AND rule3)\n if (Array.isArray(triggers[0])) {\n return (triggers as string[][]).some((subSetTriggers) =>\n subSetTriggers.every((trigger) => answers.includes(trigger))\n )\n } else {\n // rule combination kind: rule1 AND rule2\n return (triggers as string[]).every((trigger) => answers.includes(trigger))\n }\n }\n\n throw Error('[isTriggered] triggers is not typed well')\n}\n\nexport function flattenSelectedAnswers(answers: SelectedAnswersData) {\n const linearAnswers: SelectedAnswerData[] = []\n\n for (const answer of answers) {\n linearAnswers.push(...Object.values(answer))\n }\n\n return linearAnswers.flat(1)\n}\n\n/**\n * This function helps you to get a valid workflow selectedAnswers structure\n * @param workflow the workflow data to use to initialize selectedAnswers\n * @param useDefault use workflow default values or not (this is used to avoid having unset values to appear in summaries)\n * @returns a valid selectedAnswers structure\n */\nexport function getInitialisedSelectedAnswers(workflow: WorkflowData, useDefault: boolean = true) {\n return workflow.pages.map((page) => {\n const ret: any = {}\n for (const [id, question] of Object.entries(page.questions)) {\n if (question.kind === 'body-parts') {\n ret[id] = useDefault ? [] : undefined\n } else {\n ret[id] = useDefault && question.defaultValue ? question.defaultValue : undefined\n }\n }\n return ret\n })\n}\n\nexport function fillWorkflowFromPopulatedWorkflow(workflow: WorkflowData, populatedWorkflow: PopulatedWorkflowData) {\n const filledWorkflow = JSON.parse(JSON.stringify(workflow))\n\n if (!filledWorkflow.selectedAnswers) {\n filledWorkflow.selectedAnswers = getInitialisedSelectedAnswers(filledWorkflow, false)\n }\n\n filledWorkflow.pages.forEach((page: WorkflowPageData, pageIdx: number) => {\n const ret: any = {}\n for (const [id] of Object.entries(page.questions)) {\n if (populatedWorkflow.fields[id]) {\n if (filledWorkflow.selectedAnswers)\n filledWorkflow.selectedAnswers[pageIdx][id] = populatedWorkflow.fields[id].answer as\n | string\n | string[]\n }\n }\n })\n\n return filledWorkflow\n}\n","import {\n Consult,\n ConsultationImageMeta,\n ConsultationMeta,\n ConsultRequest,\n DocumentType,\n IdentityResponse,\n IndexKey,\n MedicalMeta,\n MedicalStatus,\n MetadataCategory,\n PersonalMeta,\n PopulatedWorkflowData,\n Practitioner,\n PreferenceMeta,\n RawConsultationMeta,\n Term,\n Terms,\n Uuid,\n VaultIndex,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport {\n filterTriggeredAnsweredWithKind,\n getImagesFromIndexDb,\n getWorkflowDataByCategory,\n identificationToPersonalInformations,\n OroClient,\n RegisterPatientOutput,\n toActualObject,\n} from '..'\n\nconst MAX_RETRIES = 15\n\n/**\n * Completes a registration for a user retrying the complete flow a maximum of 15 times\n *\n * @description The order of importance when registering:\n * Creates a consultation if none exist\n * Retrieves or create's a lockbox if none exist\n * Grants the lockbox (if new) to all practitioners in the practice\n * Stores or fetches the patient data (without images)\n * Indexes the lockbox to the consult for all practitioners (done after inserting since index can be rebuilt from grants)\n * Stores the image data - done last since the majority of failure cases occur here\n * Creates the recovery payloads if they don't exist\n *\n * @param patientUuid\n * @param consultRequest\n * @param workflow\n * @param oroClient\n * @param masterKey\n * @param recoveryQA\n * @param indexSearch create search index for the consultation if true\n * @param onProgress callback that is called whenever a new step of patient registration is executed. Note: progress ranges from 0 to 1, and descriptionKey is a description of the progress as a key so the app would use it to translate the description\n * @returns the successful registration\n */\nexport async function registerPatient(\n patientUuid: Uuid,\n consultRequest: ConsultRequest,\n workflow: WorkflowData,\n oroClient: OroClient,\n masterKey?: Uuid,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n },\n indexSearch: boolean = true,\n onProgress?: (\n progress: number,\n descriptionKey: string,\n extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }\n ) => void\n): Promise<RegisterPatientOutput> {\n let consult: Consult | undefined = undefined\n let lockboxUuid: Uuid | undefined = undefined\n let practitionerAdmin: Uuid | undefined = undefined\n let retry = MAX_RETRIES\n let identity: IdentityResponse | undefined = undefined\n let errorsThrown: Error[] = []\n const stepsTotalNum = 9\n let currentStep: number\n\n for (; retry > 0; retry--) {\n try {\n currentStep = 0\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'retrieve_practitioners')\n\n // Wait a bit each retry (we also want the first one to wait)\n await new Promise((resolve) => setTimeout(resolve, 2000))\n\n // Retrieving practitioners\n if (!practitionerAdmin)\n practitionerAdmin = (await oroClient.practiceClient.practiceGetFromUuid(consultRequest.uuidPractice))\n .uuidAdmin\n\n let practitioners: Practitioner[] = await oroClient.practiceClient\n .practiceGetPractitioners(consultRequest.uuidPractice)\n .catch((err) => {\n console.log(`Error retrieving practitioners`, err)\n return []\n })\n\n // Creating consult\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_consult')\n\n if (!consult) {\n consult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n }\n\n // Creating lockbox\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_lockbox')\n\n if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)\n\n if (!identity) identity = await oroClient.guardClient.identityGet(patientUuid)\n\n await oroClient.grantLockbox(practitionerAdmin, lockboxUuid).catch((err) => {\n console.error(`Error while granting lockbox to practitioner admin ${practitionerAdmin}`, err)\n // if we cannot grant to the admin, then the registration will fail\n errorsThrown.push(err)\n })\n\n // Patient Grant to practice\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'grant_patient')\n\n let grantPromises = practitioners\n .filter((practitioner) => practitioner.uuid !== practitionerAdmin)\n .map(async (practitioner) => {\n return oroClient.grantLockbox(practitioner.uuid, lockboxUuid!).catch((err) => {\n console.error(`Error while granting lockbox to practitioner`, err)\n // Acceptable to continue as admin has already been granted, but we should still retry until the last retry remains\n if (retry <= 1) return\n errorsThrown.push(err)\n })\n })\n\n const consultIndex: VaultIndex = {\n [IndexKey.ConsultationLockbox]: [\n {\n grant: {\n lockboxUuid,\n lockboxOwnerUuid: patientUuid,\n },\n consultationId: consult.uuid,\n },\n ],\n }\n\n // the index will identify in which lockbox a consultation resides\n let consultIndexPromises = practitioners.map(async (practitioner) => {\n return oroClient.vaultIndexAdd(consultIndex, practitioner.uuid).catch((err) => {\n console.error(\n `[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`,\n err\n )\n // Acceptable to continue as the index can be rebuilt, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n })\n\n await storeImageAliases(\n consult.uuid,\n lockboxUuid,\n workflow,\n oroClient,\n onProgress\n ? {\n onProgress,\n currentStep,\n stepsTotalNum,\n }\n : undefined\n ).catch((err) => {\n console.error('[SDK: registration] Some errors happened during image upload', err)\n // Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n ++currentStep\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'store_patient_data')\n\n await storePatientData(\n consult.uuid,\n consultRequest.isoLanguageRequired,\n lockboxUuid,\n workflow,\n oroClient\n ).catch((err) => {\n console.error('[SDK: registration] Some errors happened during patient data upload', err)\n errorsThrown.push(err)\n })\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_masterkey')\n\n if (masterKey && !identity?.recoveryMasterKey) {\n // generate and store recovery payload and updates the identity\n identity = await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {\n console.error(`[SDK: registration] Error while updating master key`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n } else {\n // we did not set the master key so we do not return it\n masterKey = undefined\n }\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_security_questions')\n\n if (recoveryQA && !identity?.recoverySecurityQuestions)\n // Patient security question recovery threshold is 2 answers and updates the identity\n identity = await oroClient\n .updateSecurityQuestions(\n patientUuid,\n recoveryQA.recoverySecurityQuestions,\n recoveryQA.recoverySecurityAnswers,\n 2\n )\n .catch((err) => {\n console.error(`[SDK: registration] Error while updating security questions`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n\n await Promise.all([...grantPromises, ...consultIndexPromises])\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'search_indexing')\n\n if (indexSearch) {\n await buildConsultSearchIndex(consult, workflow, oroClient).catch((err) => {\n console.error(\n '[SDK: registration] personal information not found or another error occured during search indexing',\n err\n )\n if (retry <= 1) return // this statement is to avoid failing the registration due to the failure in search indexing the consult, this practically implements a soft retry\n errorsThrown.push(err)\n })\n }\n\n if (errorsThrown.length > 0) throw errorsThrown\n\n // Deem the consultation as ready\n await oroClient.consultClient.updateConsultByUUID(consult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n\n // if we got through the complete flow, the registration succeeded\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'success')\n\n break\n } catch (err) {\n console.error(`[SDK] Error occured during registration: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n\n if (retry <= 0) {\n console.error('[SDK] registration failed: MAX_RETRIES reached')\n throw 'RegistrationFailed'\n }\n\n console.log('Successfully Registered')\n await oroClient.cleanIndex()\n return {\n masterKey,\n consultationId: consult!.uuid,\n lockboxUuid: lockboxUuid!,\n }\n}\n\n/**\n * Creates a consultation if one has not been created and fails to be retrieved by the payment intent\n * @param consult\n * @param oroClient\n * @returns the consult Uuid\n */\nasync function getOrCreatePatientConsultationUuid(consult: ConsultRequest, oroClient: OroClient): Promise<Consult> {\n let payment = await oroClient.practiceClient.practiceGetPayment(\n consult.uuidPractice,\n consult.idStripeInvoiceOrPaymentIntent\n )\n if (payment && payment.uuidConsult) {\n return oroClient.consultClient.getConsultByUUID(payment.uuidConsult).catch((err) => {\n console.error('Error while retrieving consult', err)\n throw err\n })\n } else {\n return await oroClient.consultClient.consultCreate(consult).catch((err) => {\n console.error('Error while creating consult', err)\n throw err\n })\n }\n}\n\n/**\n * Creates a new lockbox for the patient if they do not have any, otherwise, use the first (and only one)\n * @param oroClient\n * @returns the lockbox Uuid\n */\nasync function getOrCreatePatientLockbox(oroClient: OroClient): Promise<Uuid> {\n let grants = await oroClient.getGrants()\n if (grants.length > 0) {\n console.log('The grant has already been created, skipping lockbox create step')\n return grants[0].lockboxUuid!\n } else {\n let lockboxResponse = await oroClient.vaultClient.lockboxCreate().catch((err) => {\n console.error('Error while creating lockbox', err)\n throw err\n })\n // Since the creation of a lockbox will change the scope of a user, we will force refresh the tokens\n let tokens = await oroClient.guardClient.authRefresh()\n await oroClient.guardClient.setTokens({ accessToken: tokens.accessToken, refreshToken: tokens.refreshToken })\n await oroClient.guardClient.whoAmI(true)\n\n return lockboxResponse.lockboxUuid\n }\n}\n\n/**\n * Store all patient related information into his/her lockbox\n * @param consultationId The consultation id\n * @param isoLanguage the prefered language of communication (ISO 639-3 https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes)\n * @param lockboxUuid the lockbox uuid to store data in\n * @param workflow the workflow used to extract informations\n * @param oroClient an oroClient instance\n * @returns\n */\nasync function storePatientData(\n consultationId: Uuid,\n isoLanguage: string,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient\n): Promise<(Uuid | void)[]> {\n // Create and store registration data\n return Promise.all([\n // Storing Raw data first\n oroClient.getOrInsertJsonData<RawConsultationMeta>(\n lockboxUuid,\n workflow,\n {\n category: MetadataCategory.Raw,\n contentType: 'application/json',\n consultationId,\n },\n {}\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Consultation).then((data) =>\n oroClient.getOrInsertJsonData<ConsultationMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, // TODO: deprecated. Will finally only be in privateMetadata\n },\n { consultationId },\n false,\n true // the only data that needs to include an email notification\n )\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Medical).then((data) =>\n oroClient.getOrInsertJsonData<MedicalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Medical,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId!],\n },\n {}\n )\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.Personal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.ChildPersonal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.OtherPersonal,\n oroClient\n ),\n oroClient.getOrInsertJsonData<PreferenceMeta>(\n lockboxUuid,\n { isoLanguage },\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {}\n ),\n ]).then((dataUuids) => dataUuids.flat())\n}\n\nasync function storeImageAliases(\n consultationId: Uuid,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient,\n progress?: {\n currentStep: number\n stepsTotalNum: number\n onProgress: (\n progress: number,\n descriptionKey: string,\n extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }\n ) => void\n }\n): Promise<(Uuid | void)[]> {\n const images = await getImagesFromIndexDb((await filterTriggeredAnsweredWithKind(workflow, 'images-alias')).flat())\n\n const nonNullImages = images.filter((img) => !!img)\n\n if (images.length !== nonNullImages.length) {\n console.error('[SDK] Some images have not been found, they have been skipped.')\n }\n\n let storedImagesNum = 0\n let totalImagesNum = nonNullImages.length\n if (progress)\n progress.onProgress(progress.currentStep / progress.stepsTotalNum, 'store_images', {\n storedImagesNum,\n totalImagesNum,\n })\n\n let promises = nonNullImages.map((image) => {\n return oroClient\n .getOrInsertJsonData<ConsultationImageMeta>(\n lockboxUuid,\n image,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.ImageAlias,\n consultationId,\n idbId: image.idbId as string,\n },\n {}\n )\n .then(() => {\n if (progress) {\n ++storedImagesNum\n let progressStepValue =\n Math.round(\n ((progress.currentStep + 1) / progress.stepsTotalNum -\n progress.currentStep / progress.stepsTotalNum) *\n 100\n ) / 100\n progress.onProgress(\n progress.currentStep / progress.stepsTotalNum +\n progressStepValue * (storedImagesNum / totalImagesNum),\n 'store_images',\n {\n storedImagesNum,\n totalImagesNum,\n }\n )\n }\n })\n })\n return Promise.all(promises)\n}\n\n/**\n * Extracts the workflow MetadataCategory for Personal, ChildPersonal and OtherPersonal\n * then stores it in the vault\n *\n * @param workflow\n * @param lockboxUuid\n * @param category\n * @returns The data uuid\n */\nexport async function extractAndStorePersonalWorkflowData(\n workflow: WorkflowData,\n lockboxUuid: Uuid,\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n oroClient: OroClient\n): Promise<Uuid | void> {\n return getWorkflowDataByCategory(workflow, category as unknown as MetadataCategory).then((data) => {\n if (Object.keys(data.fields).length === 0) return\n return oroClient.getOrInsertJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n {}\n )\n })\n}\n\n/**\n * Given workflow data, it populates it with Personal, ChildPersonal, and OtherPersonal workflow data\n * @param workflow\n */\nexport async function extractPersonalInfoFromWorkflowData(workflow: WorkflowData): Promise<{\n personalInfoPopulatedWfData: PopulatedWorkflowData\n childPersonalInfoPopulatedWfData: PopulatedWorkflowData\n otherPersonalInfoPopulatedWfData: PopulatedWorkflowData\n}> {\n return Promise.all([\n getWorkflowDataByCategory(workflow, MetadataCategory.Personal),\n getWorkflowDataByCategory(workflow, MetadataCategory.ChildPersonal),\n getWorkflowDataByCategory(workflow, MetadataCategory.OtherPersonal),\n ]).then(([personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData]) => {\n return {\n personalInfoPopulatedWfData,\n childPersonalInfoPopulatedWfData,\n otherPersonalInfoPopulatedWfData,\n }\n })\n}\n\n/**\n * Creates the search index for the first name, last name, and the short id of the given consultation\n * @param consult the consultation to be search indexed\n * @param workflow the workflow data\n * @param oroClient\n */\nexport async function buildConsultSearchIndex(consult: Consult, workflow: WorkflowData, oroClient: OroClient) {\n let terms: Terms = [\n <Term>{\n kind: 'consult-shortid',\n value: consult.shortId,\n },\n ]\n\n const { personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData } =\n await extractPersonalInfoFromWorkflowData(workflow)\n\n const personalInfo = identificationToPersonalInformations(\n toActualObject(personalInfoPopulatedWfData),\n MetadataCategory.Personal\n )\n const childPersonalInfo = identificationToPersonalInformations(\n toActualObject(childPersonalInfoPopulatedWfData),\n MetadataCategory.ChildPersonal\n )\n const otherPersonalInfo = identificationToPersonalInformations(\n toActualObject(otherPersonalInfoPopulatedWfData),\n MetadataCategory.OtherPersonal\n )\n\n terms.push(\n <Term>{\n kind: 'first-name',\n value: personalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: personalInfo.name,\n }\n )\n\n if (childPersonalInfo.firstname && childPersonalInfo.name) {\n terms.push(\n <Term>{\n kind: 'first-name',\n value: childPersonalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: childPersonalInfo.name,\n }\n )\n }\n\n if (otherPersonalInfo.firstname && otherPersonalInfo.name) {\n terms.push(\n <Term>{\n kind: 'first-name',\n value: otherPersonalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: otherPersonalInfo.name,\n }\n )\n }\n\n await oroClient.searchClient.index(consult.uuid, terms)\n}\n","import { CryptoRSA, uuidParse} from \"oro-toolbox\"\nimport { EncryptedIndexEntry, Grant, IndexConsultLockbox } from \"oro-sdk-apis\"\n\n/**\n * Decrypts and returns the encrypted grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedGrants: an array of encrypted grants\n * @param rsaKey: the rsa key used to decrypt the encrypted grants\n * @returns an array of grants\n */\nexport function decryptGrants(encryptedGrants: Grant[], rsaKey: CryptoRSA): Grant[] {\n return encryptedGrants\n .map(grant => {\n if (grant.encryptedLockbox && !grant.lockboxUuid) {\n try {\n grant.lockboxUuid = uuidParse(\n rsaKey.base64DecryptToBytes(grant.encryptedLockbox)\n )\n } catch (e) {\n console.error('[sdk:index] The grant could not be decrypted or was not a valid UUID: ', e)\n }\n }\n return grant\n })\n .filter(grant => grant.lockboxUuid)\n}\n\n/**\n * Decrypts the encrypted consult lockboxes and returns their grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedConsultLockboxes: an array of encrypted entries\n * @param rsaKey: the rsa key used to decrypt the encrypted entries\n * @returns an array of grants\n */\nexport function decryptConsultLockboxGrants(encryptedConsultLockboxes: EncryptedIndexEntry[], rsaKey: CryptoRSA): Grant[] {\n return encryptedConsultLockboxes\n .map(encryptedConsultLockboxes => {\n try {\n return [true, (rsaKey.base64DecryptToJson(\n encryptedConsultLockboxes.encryptedIndexEntry\n ) as IndexConsultLockbox).grant]\n } catch(e) {\n console.error('[sdk:index] The consult lockbox grant could not be decrypted: ', e)\n return [false, undefined] // if decryption fails, we want to ignore the grant but not fail the call\n }\n })\n .filter(grantsTuple => grantsTuple[0])\n .map(grantTuples => grantTuples[1] as Grant)\n}","import { IndexKey, Grant, IndexConsultLockbox, MetadataCategory, VaultIndex } from 'oro-sdk-apis'\nimport { OroClient, Uuid } from '..'\n\n/**\n * @name filterGrantsWithLockboxMetadata\n * @description searches for the existance of a consult uuid in each granted lockbox\n * @param oroClient\n * @param filter: the consult uuid\n * @returns the grants containing the consult uuid\n */\nexport async function filterGrantsWithLockboxMetadata(\n oroClient: OroClient,\n filter: { consultationId: Uuid },\n): Promise<Grant[]> {\n let grants = await oroClient.getGrants()\n let filteredGrants = []\n for (let grant of grants) {\n // Fetches in each lockbox the existance of a given consult id\n let consultationIdExistsInMetadata = await oroClient.vaultClient.lockboxMetadataGet(grant.lockboxUuid!, ['consultationId'], [], {\n category: MetadataCategory.Consultation,\n consultationId: filter.consultationId\n })\n // If there are entries in the metadata, it means that the consult exists in the lockbox\n if (consultationIdExistsInMetadata[0].length >= 0)\n filteredGrants.push(grant)\n }\n\n return filteredGrants\n}\n","import {\n AllRoleType,\n AuthTokenRequest,\n Consult,\n ConsultRequest,\n ConsultService,\n DataCreateResponse,\n DiagnosisService,\n Document,\n DocumentType,\n EncryptedIndexEntry,\n EncryptedVaultIndex,\n Grant,\n GuardService,\n IdentityCreateRequest,\n IdentityResponse,\n IndexConsultLockbox,\n IndexKey,\n LocalizedData,\n LockboxDataRequest,\n LockboxGrantRequest,\n LockboxManifest,\n ManifestEntry,\n Meta,\n Metadata,\n MetadataCategory,\n OtherRoleType,\n PersonalMeta,\n PopulatedWorkflowData,\n Practice,\n PracticeService,\n PractitionnerRoleType,\n PreferenceMeta,\n RecoveryMeta,\n RoleBasedScopes,\n SearchService,\n SecretShard,\n TellerService,\n TokenData,\n TosAndCpAcceptanceRequest,\n Uuid,\n VaultIndex,\n VaultService,\n WorkflowData,\n WorkflowService,\n} from 'oro-sdk-apis'\nimport * as OroToolbox from 'oro-toolbox'\nimport { CryptoRSA } from 'oro-toolbox'\nimport { decryptConsultLockboxGrants, decryptGrants, registerPatient, sessionStorePrivateKeyName } from './helpers'\nimport {\n AssociatedLockboxNotFound,\n IncompleteAuthentication,\n LocalEncryptedData,\n MissingGrant,\n MissingGrantFilter,\n MissingLockbox,\n MissingLockboxOwner,\n RecoveryData,\n RegisterPatientOutput,\n UserPreference,\n} from './models'\nimport { filterGrantsWithLockboxMetadata } from './sdk-revision'\n\nexport class OroClient {\n private rsa?: CryptoRSA\n private secrets: {\n lockboxUuid: string\n cryptor: OroToolbox.CryptoChaCha\n }[] = []\n private cachedMetadataGrants: {\n [filter: string]: Grant[]\n } = {}\n\n private cachedManifest: {\n [filter: string]: ManifestEntry[]\n } = {}\n\n private vaultIndex?: VaultIndex\n\n constructor(\n private toolbox: typeof OroToolbox,\n public tellerClient: TellerService,\n public vaultClient: VaultService,\n public guardClient: GuardService,\n public searchClient: SearchService,\n public practiceClient: PracticeService,\n public consultClient: ConsultService,\n public workflowClient: WorkflowService,\n public diagnosisClient: DiagnosisService,\n private authenticationCallback?: (err: Error) => void\n ) {}\n\n /**\n * clears the vaultIndex and cached metadata grants\n */\n public async cleanIndex() {\n this.cachedMetadataGrants = {}\n this.cachedManifest = {}\n }\n\n /**\n * Generates an RSA key pair and password payload (rsa private key encrypted with the password)\n * Calls Guard to sign up with the email address, password, practice, legal and token data\n *\n * @param email\n * @param password\n * @param practice\n * @param legal\n * @param tokenData\n * @returns\n */\n public async signUp(\n email: string,\n password: string,\n practice: Practice,\n tosAndCpAcceptance: TosAndCpAcceptanceRequest,\n tokenData?: TokenData,\n subscription?: boolean,\n skipEmailValidation?: boolean\n ): Promise<IdentityResponse> {\n this.rsa = new CryptoRSA()\n const privateKey = this.rsa.private()\n\n const symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n const recoveryPassword = symmetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n\n const emailConfirmed = !!skipEmailValidation\n\n const signupRequest: IdentityCreateRequest = {\n practiceUuid: practice.uuid,\n email: email.toLowerCase(),\n emailConfirmed,\n password: hashedPassword,\n publicKey: this.toolbox.encodeToBase64(this.rsa.public()),\n recoveryPassword,\n tosAndCpAcceptance,\n tokenData,\n subscription,\n }\n\n const identity = await this.guardClient.identityCreate(signupRequest)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(identity.id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n return identity\n }\n\n /**\n * Parse the given accessToken claims by calling guard whoami and update theidentity to set it's emailConfirmed flag\n * @param accessToken\n * @returns The identity related to confirmedEmail\n */\n public async confirmEmail(accessToken: string): Promise<IdentityResponse> {\n this.guardClient.setTokens({ accessToken })\n const claims = await this.guardClient.whoAmI()\n return this.guardClient.identityUpdate(claims.sub, {\n emailConfirmed: true,\n })\n }\n\n /**\n * Calls Guard to sign in with the email address, password and one time password (if MFA is enabled)\n * Then recover's the rsa private key from the recovery payload\n *\n * @param practiceUuid\n * @param email\n * @param password\n * @param otp\n * @returns the user identity\n */\n public async signIn(practiceUuid: Uuid, email: string, password: string, otp?: string): Promise<IdentityResponse> {\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n const tokenRequest: AuthTokenRequest = {\n practiceUuid,\n email: email.toLowerCase(),\n password: hashedPassword,\n otp,\n }\n\n await this.guardClient.authToken(tokenRequest)\n const userUuid = (await this.guardClient.whoAmI()).sub\n\n // Updates the rsa key to the one generated on the backend\n await this.recoverPrivateKeyFromPassword(userUuid, password)\n return await this.guardClient.identityGet(userUuid)\n }\n\n /**\n * Will attempt to recover an existing login session and set back\n * the private key in scope\n */\n public async resumeSession() {\n const id = (await this.guardClient.whoAmI()).sub\n const recoveryPayload = sessionStorage.getItem(sessionStorePrivateKeyName(id))\n const recoveryKey = (await this.guardClient.identityGet(id)).recoveryLogin\n\n if (!recoveryKey || !recoveryPayload) throw IncompleteAuthentication\n\n const symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(recoveryKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * This function let's you encrypt locally an Object\n * @param value the Object to encrypt\n * @returns a LocalEncryptedData Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localEncryptToJsonPayload(value: any): LocalEncryptedData {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = new this.toolbox.CryptoChaCha()\n\n const encryptedData = chaChaKey.jsonEncryptToBase64Payload(value)\n const encryptedKey = this.toolbox.encodeToBase64(this.rsa.encryptToBytes(chaChaKey.key()))\n\n return { encryptedData, encryptedKey }\n }\n\n /**\n * This function let's you decrypt a LocalEncryptedData object\n * @param value a LocalEncryptedData object\n * @returns a decrypted Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localDecryptJsonPayload({ encryptedKey, encryptedData }: LocalEncryptedData): any {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = this.rsa.base64DecryptToBytes(encryptedKey)\n const decryptedData = this.toolbox.CryptoChaCha.fromKey(chaChaKey).base64PayloadDecryptToJson(encryptedData)\n\n return decryptedData\n }\n\n /**\n * Effectively kills your \"session\"\n */\n public async signOut() {\n this.rsa = undefined\n this.secrets = []\n this.guardClient.setTokens({\n accessToken: undefined,\n refreshToken: undefined,\n })\n await this.guardClient.authLogout()\n }\n\n /**\n * @name registerPatient\n * @description The complete flow to register a patient\n *\n * Steps:\n * 1. Create a consult (checks if payment has been done)\n * 2. Creates a lockbox\n * 3. Grants lockbox access to all practice personnel\n * 4. Creates secure identification, medical, onboarding data\n * 5. Generates and stores the rsa key pair and recovery payloads\n *\n * @param patientUuid\n * @param consult\n * @param workflow\n * @param recoveryQA\n * @param indexSearch create search index for the consultation if true\n * @param onProgress callback that is called whenever a new step of patient registration is executed. Note: progress ranges from 0 to 1, and descriptionKey is a description of the progress as a key so the app would use it to translate the description\n * @returns\n */\n public async registerPatient(\n patientUuid: Uuid,\n consult: ConsultRequest,\n workflow: WorkflowData,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n },\n indexSearch: boolean = true,\n onProgress?: (progress: number, descriptionKey: string) => void\n ): Promise<RegisterPatientOutput> {\n if (!this.rsa) throw IncompleteAuthentication\n return registerPatient(\n patientUuid,\n consult,\n workflow,\n this,\n this.toolbox.uuid(),\n recoveryQA,\n indexSearch,\n onProgress\n )\n }\n\n /**\n * Fetches all grants, and consultations that exist in each lockbox\n * Then updates the index for the current user with the lockbox consult relationship\n */\n public async forceUpdateIndexEntries() {\n let grants = await this.getGrants()\n\n let indexConsultLockbox: IndexConsultLockbox[] = await Promise.all(\n grants.map(\n async (grant: Grant) =>\n await this.vaultClient\n .lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n [],\n { category: MetadataCategory.Consultation },\n grant.lockboxOwnerUuid\n )\n .then((consults) => {\n try {\n return consults[0].map((consult: any) => {\n return {\n ...consult,\n grant: {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid,\n },\n }\n })\n } catch (e) {\n // No consultations in lockbox or index could not be created\n return []\n }\n })\n .catch(() => [])\n )\n ).then((consults) => consults.flat())\n this.vaultIndexAdd({\n [IndexKey.Consultation]: indexConsultLockbox,\n })\n .then(() => alert('The Index was successfully updated!'))\n .catch(() => console.error('The index failed to update!'))\n }\n\n /**\n * Generates, encrypts and adds entries to vault index for a given index owner\n *\n * @param entries\n * @param indexOwnerUuid\n */\n public async vaultIndexAdd(entries: VaultIndex, indexOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let rsaPub: Uint8Array\n if (indexOwnerUuid) {\n let base64IndexOwnerPubKey = (await this.guardClient.identityGet(indexOwnerUuid)).publicKey\n rsaPub = this.toolbox.decodeFromBase64(base64IndexOwnerPubKey)\n } else {\n rsaPub = this.rsa.public()\n }\n\n let encryptedIndex: EncryptedVaultIndex = {}\n\n for (let keyString of Object.keys(entries)) {\n let key = keyString as keyof VaultIndex\n switch (key) {\n case IndexKey.ConsultationLockbox:\n encryptedIndex[key] = (entries[key] as IndexConsultLockbox[])\n .map((e) => ({\n ...e,\n uniqueHash: e.consultationId,\n }))\n .map(\n (e: IndexConsultLockbox) =>\n ({\n uuid: e.uuid,\n timestamp: e.timestamp,\n uniqueHash: e.uniqueHash,\n encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(\n {\n consultationId: e.consultationId,\n grant: e.grant,\n },\n rsaPub\n ),\n } as EncryptedIndexEntry)\n )\n break\n }\n }\n await this.vaultClient.vaultIndexPut(encryptedIndex, indexOwnerUuid)\n }\n\n /**\n * @name grantLockbox\n * @description Grants a lockbox by retrieving the shared secret of the lockbox and encrypting it with the grantees public key\n * @param granteeUuid\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n */\n public async grantLockbox(granteeUuid: Uuid, lockboxUuid: Uuid, lockboxOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let secret = (await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)).key()\n let base64GranteePublicKey = (await this.guardClient.identityGet(granteeUuid)).publicKey\n let granteePublicKey = this.toolbox.decodeFromBase64(base64GranteePublicKey)\n\n let granteeEncryptedSecret = CryptoRSA.bytesWithPubEncryptToBase64(secret, granteePublicKey)\n let request: LockboxGrantRequest = {\n encryptedSecret: granteeEncryptedSecret,\n granteeUuid: granteeUuid,\n }\n await this.vaultClient.lockboxGrant(lockboxUuid, request, lockboxOwnerUuid)\n }\n\n /**\n * @name createMessageData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a message string\n * @param lockboxUuid\n * @param message\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageData(\n lockboxUuid: Uuid,\n message: string,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(message)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: 'text/plain',\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createMessageAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(new Uint8Array(await data.arrayBuffer()))\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n lastModified: data.lastModified,\n size: data.size,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: data.type,\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param category the category for the attachment data\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createConsultationAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n documentType: DocumentType,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n return this.createBytesData<Meta | any>(\n lockboxUuid,\n new Uint8Array(await data.arrayBuffer()),\n {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType,\n contentType: data.type,\n },\n {\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n },\n lockboxOwnerUuid,\n previousDataUuid,\n withNotification\n )\n }\n\n /**\n * @name createJsonData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a JSON\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createJsonData<T extends Metadata>(\n lockboxUuid: Uuid,\n data: any,\n meta?: T,\n privateMeta?: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n if (withNotification)\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * Get or upsert a data in lockbox\n * @param lockboxUuid the lockbox uuid\n * @param data the data to insert\n * @param publicMetadata the public Metadata\n * @param privateMetadata the private Metadata\n * @param forceReplace set true when the insertion of data requires to replace the data when it exists already\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async getOrInsertJsonData<M extends Metadata>(\n lockboxUuid: Uuid,\n data: any,\n publicMetadata: M,\n privateMetadata: Metadata,\n forceReplace: boolean = false,\n withNotification: boolean = false\n ): Promise<Uuid> {\n let manifest = await this.vaultClient.lockboxManifestGet(lockboxUuid, publicMetadata)\n if (!forceReplace && manifest.length > 0) {\n console.log(`The data for ${JSON.stringify(publicMetadata)} already exist`)\n return manifest[0].dataUuid\n } else\n return (\n await this.createJsonData<M>(\n lockboxUuid,\n data,\n publicMetadata,\n privateMetadata,\n undefined,\n forceReplace && manifest.length > 0 ? manifest[0].dataUuid : undefined, // if forceReplace and data already exist, then replace data. Otherwise insert it\n withNotification\n ).catch((err) => {\n console.error(`Error while upserting data ${JSON.stringify(publicMetadata)} data`, err)\n throw err\n })\n ).dataUuid\n }\n\n /**\n * @name createBytesData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a Bytes\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createBytesData<T extends Metadata>(\n lockboxUuid: Uuid,\n data: Uint8Array,\n meta: T,\n privateMeta: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n if (withNotification)\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name getJsonData\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * Decrypts the data to a valid JSON object. If this is impossible, the call to the WASM binary will fail\n *\n * @type T is the generic type specifying the return type object of the function\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the data specified by the generic type <T>\n */\n public async getJsonData<T = any>(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<T> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToJson(encryptedPayload.data)\n }\n /**\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the bytes data\n */\n public async getBytesData(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<Uint8Array> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToBytes(encryptedPayload.data)\n }\n\n /**\n * @name getGrants\n * @description Get all lockboxes granted to user with the applied filter\n * @note this function returns cached grants and will not update unless the page is refreshed\n * @todo some versions of lockboxes do not make use of lockbox metadata\n * in this case, all lockboxes need to be filtered one-by-one to find the correct one\n * Remove if this is no longer the case\n * @param filter: the consultationId in which the grant exists\n * @returns decrypted lockboxes granted to user\n */\n public async getGrants(filter?: { consultationId: Uuid }): Promise<Grant[]> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let filterString = JSON.stringify(filter)\n // retrieves cached grants\n if (this.cachedMetadataGrants[filterString]) return this.cachedMetadataGrants[filterString]\n\n // We're using the account role to determine the way a grant is accessed\n let currentAccountRole = await this.getAccountRole()\n if (currentAccountRole.length === 1 && currentAccountRole[0] === OtherRoleType.User) return []\n\n if (\n [OtherRoleType.Patient, OtherRoleType.User].every((requiredRole) =>\n currentAccountRole.includes(requiredRole)\n )\n ) {\n let encryptedGrants\n // if there are no grants with the applied filter from index, attempt for naive filter with backwards compatibility\n if (filter) {\n encryptedGrants = await filterGrantsWithLockboxMetadata(this, filter)\n } else {\n encryptedGrants = (await this.vaultClient.grantsGet()).grants\n }\n const decryptedGrants = await decryptGrants(encryptedGrants, this.rsa)\n // sets the cached grant\n this.cachedMetadataGrants[filterString] = decryptedGrants\n console.info('[sdk:grant] Found grant for patient')\n return decryptedGrants\n }\n // if not a patient, then a practitioner is trying to retrieve a grant, it **Must** contain a filter, otherwise too many grants are possible\n if (!filter) throw MissingGrantFilter\n // Note: will work only if the filter being applied is exclusively a consult id\n const grantsByConsultLockbox = await this.vaultClient\n .vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])\n .then((res) => res[IndexKey.ConsultationLockbox])\n .catch((e) => {\n console.error(e)\n return []\n })\n\n const decryptedConsults = decryptConsultLockboxGrants(grantsByConsultLockbox ?? [], this.rsa)\n if (decryptedConsults.length > 0) {\n console.info('[sdk:index] Grants found in user`s constant time secure index')\n this.cachedMetadataGrants[filterString] = decryptedConsults\n return this.cachedMetadataGrants[filterString]\n }\n\n // if we have no valid grants, then return nothing\n return []\n }\n\n /**\n * Fetches the role of the account that is logged in\n *\n * @returns the role based scopes defined by the whoami\n */\n async getAccountRole(): Promise<RoleBasedScopes[]> {\n return (await this.guardClient.whoAmI()).scope.split(' ') as RoleBasedScopes[]\n }\n\n /**\n * @name getCachedSecretCryptor\n * @description Retrieves the cached lockbox secret or fetches the secret from vault, then creates the symmetric cryptor and stores it in memory\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns\n */\n async getCachedSecretCryptor(lockboxUuid: string, lockboxOwnerUuid?: string): Promise<OroToolbox.CryptoChaCha> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let index = this.secrets.findIndex((secret) => secret.lockboxUuid === lockboxUuid)\n if (index === -1) {\n let encryptedSecret = (await this.vaultClient.lockboxSecretGet(lockboxUuid, lockboxOwnerUuid)).sharedSecret\n\n let secret = this.rsa.base64DecryptToBytes(encryptedSecret)\n let cryptor = this.toolbox.CryptoChaCha.fromKey(secret)\n this.secrets.push({ lockboxUuid, cryptor })\n return cryptor\n } else {\n return this.secrets[index].cryptor\n }\n }\n\n /**\n * Retrieves the patient personal information associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several personal informations data\n * @param consultationId The consultation Id\n * @param category The personal MetadataCategory to fetch\n * @param forceRefresh force data refresh (default to false)\n * @returns the personal data\n */\n public async getPersonalInformationsFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, category, forceRefresh)\n }\n\n /**\n * Retrieves the patient medical data associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several medical data\n * @param consultationId The consultation Id\n * @param forceRefresh force data refresh (default to false)\n * @returns the medical data\n */\n public async getMedicalDataFromConsultId(\n consultationId: Uuid,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, MetadataCategory.Medical, forceRefresh)\n }\n\n private async getMetaCategoryFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n let grants = await this.getGrants({ consultationId })\n let workflowData: LocalizedData<PopulatedWorkflowData>[] = []\n for (let grant of grants) {\n let manifest = await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n\n // TODO: find another solution for backwards compatibility (those without the metadata consultationIds)\n if (manifest.length === 0) {\n manifest = (\n await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n // backward compatiblility with TonTest\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n ).filter((entry) => !entry.metadata.consultationIds) // Keep only entries without associated consultationIds\n }\n let data = await Promise.all(\n manifest.map(async (entry) => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n dataUuid: entry.dataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(grant.lockboxUuid!, entry.dataUuid),\n }\n })\n )\n workflowData = { ...workflowData, ...data }\n }\n return workflowData\n }\n\n /**\n * @description retrieves the personal information stored in the first owned lockbox\n * @param userId The user Id\n * @returns the personal data\n */\n public async getPersonalInformations(userId: Uuid): Promise<LocalizedData<PopulatedWorkflowData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === userId)\n\n if (!grant) {\n throw MissingGrant\n }\n\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n false,\n userId\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * Retrieves the grant associated to a consultationId\n * @note returns the first grant only\n * @param consultationId The consultationId\n * @returns the grant\n */\n public async getGrantFromConsultId(consultationId: Uuid): Promise<Grant | undefined> {\n let grants = await this.getGrants({ consultationId })\n\n if (grants.length === 0) {\n throw AssociatedLockboxNotFound\n }\n\n return grants[0]\n }\n\n /**\n * retrieves the identity associated to the `consultationId`\n * @param consultationId The consultation Id\n * @returns the identity\n */\n public async getIdentityFromConsultId(consultationId: Uuid): Promise<IdentityResponse | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (grant && grant.lockboxOwnerUuid) {\n return await this.guardClient.identityGet(grant.lockboxOwnerUuid)\n } else {\n return undefined\n }\n }\n\n /**\n * retrieves the lockbox manifest for a given lockbox and add's its private metadata\n * @note the lockbox manifest will retrieved the cached manifest first unless force refresh is enabled\n * @param lockboxUuid\n * @param filter\n * @param expandPrivateMetadata\n * @param lockboxOwnerUuid\n * @param forceRefresh\n * @returns the lockbox manifest\n */\n public async getLockboxManifest(\n lockboxUuid: Uuid,\n filter: Metadata,\n expandPrivateMetadata: boolean,\n lockboxOwnerUuid?: Uuid,\n forceRefresh: boolean = false\n ): Promise<LockboxManifest> {\n let manifestKey = JSON.stringify({\n lockboxUuid,\n filter,\n expandPrivateMetadata,\n lockboxOwnerUuid,\n })\n if (!forceRefresh && this.cachedManifest[manifestKey]) return this.cachedManifest[manifestKey]\n\n return this.vaultClient.lockboxManifestGet(lockboxUuid, filter, lockboxOwnerUuid).then((manifest) => {\n return Promise.all(\n manifest.map(async (entry) => {\n if (expandPrivateMetadata && entry.metadata.privateMetadata) {\n let privateMeta = await this.getJsonData<Metadata>(\n lockboxUuid!,\n entry.metadata.privateMetadata,\n lockboxOwnerUuid\n )\n entry.metadata = {\n ...entry.metadata,\n ...privateMeta,\n }\n }\n return entry\n })\n ).then((manifest) => (this.cachedManifest[manifestKey] = manifest))\n })\n }\n\n /**\n * @description Create or update the personal information and store it in the first owned lockbox\n * @param identity The identity to use\n * @param data The personal data to store\n * @param dataUuid (optional) The dataUuid to update\n * @returns\n */\n public async createPersonalInformations(\n identity: IdentityResponse,\n data: PopulatedWorkflowData,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * Create or update user Preference\n * @param identity\n * @param preference\n * @param dataUuid\n * @returns\n */\n public async createUserPreference(\n identity: IdentityResponse,\n preference: UserPreference,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PreferenceMeta>(\n lockboxUuid,\n preference,\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * retrieves the user preference from a grant\n * @param grant The grant\n * @returns the user preference\n */\n public async getDataFromGrant<T = any>(grant: Grant, filter: Metadata): Promise<LocalizedData<T>> {\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n\n filter,\n false,\n grant.lockboxOwnerUuid,\n true\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<T>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getUserPreferenceFromConsultId(consultationId: string): Promise<LocalizedData<UserPreference>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getUserPreference(identity: IdentityResponse): Promise<LocalizedData<UserPreference>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getRecoveryDataFromConsultId(consultationId: string): Promise<LocalizedData<RecoveryData>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<RecoveryData>(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getRecoveryData(identity: IdentityResponse): Promise<LocalizedData<RecoveryData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * @name getAssignedConsultations\n * @description finds all assigned or owned consultations for the logged user\n * Steps:\n * - Retrieves all granted lockboxes given to the logged user\n * - for each lockbox, find all consultation ids\n * - for each consultation id, retrieve the consult information\n * @param practiceUuid the uuid of the practice to look consult into\n * @returns the list of consults\n */\n public async getAssignedConsultations(practiceUuid: Uuid): Promise<Consult[]> {\n return Promise.all(\n (await this.getGrants()).map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n true,\n undefined\n ).then((manifest) =>\n Promise.all(\n manifest.map(\n async (entry) =>\n await this.consultClient.getConsultByUUID(entry.metadata.consultationId, practiceUuid)\n )\n ).then((promise) => promise.flat())\n )\n )\n ).then((consults) => consults.flat())\n }\n\n /**\n * Gets the past consultations of the patient as well as his relatives if any\n * @param consultationId any consultation uuid from which we will fetch all the other consultations of the same patient as the owner of this consultation id\n * @param practiceUuid\n */\n public async getPastConsultationsFromConsultId(\n consultationId: string,\n practiceUuid: string\n ): Promise<Consult[] | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n if (!grant) return undefined\n\n let consultationsInLockbox: string[] = (\n await this.vaultClient.lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n ['consultationId'],\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n grant.lockboxOwnerUuid\n )\n )\n .flat()\n .map((metadata: { consultationId: string }) => metadata.consultationId)\n\n if (consultationsInLockbox.length == 0) return []\n\n return await Promise.all(\n consultationsInLockbox.map(async (consultId: string) => {\n return await this.consultClient.getConsultByUUID(consultId, practiceUuid)\n })\n )\n }\n\n /**\n * @name getPatientConsultationData\n * @description retrieves the consultation data\n * @param consultationId\n * @returns\n */\n public async getPatientConsultationData(\n consultationId: Uuid,\n forceRefresh: boolean = false\n ): Promise<PopulatedWorkflowData[]> {\n //TODO: make use of getPatientDocumentsList instead of doing it manually here\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, //since we want to update the cached manifest (if another consult data exists)\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n ).then((manifest) =>\n Promise.all(\n manifest.map((e) =>\n this.getJsonData<PopulatedWorkflowData>(\n grant.lockboxUuid!,\n e.dataUuid,\n grant.lockboxOwnerUuid\n )\n )\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /**\n * This function returns the patient prescriptions\n * @param consultationId\n * @returns\n */\n public async getPatientPrescriptionsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Prescription,\n },\n true,\n consultationId\n )\n }\n\n /**\n * This function returns the patient results\n * @param consultationId\n * @returns\n */\n public async getPatientResultsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Result,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns the patient treatment plan options\n * @param consultationId\n * @returns Document[] corresponding to the patient treatment plan options\n */\n public async getPatientTreatmentPlans(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns a specific patient treatment plan option\n * @param consultationId\n * @param treatmentPlanId\n * @returns\n */\n public async getPatientTreatmentPlanByUuid(consultationId: Uuid, treatmentPlanId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n treatmentPlanId,\n },\n true,\n consultationId\n )\n }\n\n /**\n * @name getPatientDocumentsList\n * @description applies the provided filter to the vault to only find those documents\n * @param filters the applied filters (e.g. type of documents)\n * @param expandPrivateMetadata whether or not, the private metadata needs to be retrieved\n * (more computationally expensive)\n * @param consultationId\n * @returns the filtered document list\n */\n public async getPatientDocumentsList(\n filters: Object,\n expandPrivateMetadata: boolean,\n consultationId: Uuid\n ): Promise<Document[]> {\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n { ...filters, consultationId },\n expandPrivateMetadata,\n grant.lockboxOwnerUuid,\n true\n ).then((manifest) =>\n Promise.all(\n manifest.map(async (entry): Promise<Document> => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n ...entry,\n }\n })\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /****************************************************************************************************************\n * RECOVERY *\n ****************************************************************************************************************/\n\n /**\n * @name recoverPrivateKeyFromSecurityQuestions\n * @description Recovers and sets the rsa private key from the answered security questions\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to recover the key\n */\n public async recoverPrivateKeyFromSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n let shards: SecretShard[] = (await this.guardClient.identityGet(id)).recoverySecurityQuestions!\n let answeredShards = shards\n .filter((shard: any) => {\n // filters all answered security questions\n let indexOfQuestion = recoverySecurityQuestions.indexOf(shard.securityQuestion)\n if (indexOfQuestion === -1) return false\n return recoverySecurityAnswers[indexOfQuestion] && recoverySecurityAnswers[indexOfQuestion] != ''\n })\n .map((item: any) => {\n // appends the security answer to the answered shards\n let index = recoverySecurityQuestions.indexOf(item.securityQuestion)\n item.securityAnswer = recoverySecurityAnswers[index]\n return item\n })\n try {\n // reconstructs the key from the answered security answers\n let privateKey = this.toolbox.reconstructSecret(answeredShards, threshold)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n } catch (e) {\n console.error(e)\n }\n }\n\n /**\n * @name recoverPrivateKeyFromPassword\n * @description Recovers and sets the rsa private key from the password\n * @param id\n * @param password\n */\n public async recoverPrivateKeyFromPassword(id: Uuid, password: string) {\n let identity = await this.guardClient.identityGet(id)\n\n let recoveryPayload = identity.recoveryPassword\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @name recoverPrivateKeyFromMasterKey\n * @description Recovers and sets the rsa private key from the master key\n * @param id\n * @param masterKey\n */\n public async recoverPrivateKeyFromMasterKey(id: Uuid, masterKey: string) {\n let recoveryPayload = (await this.guardClient.identityGet(id)).recoveryMasterKey!\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @description Generates and updates the security questions and answers payload using new recovery questions and answers\n * Important: Since the security questions generate a payload for the private key, they will never be stored on the device as they must remain secret!!!\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to rebuild the secret\n */\n public async updateSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n if (!this.rsa) throw IncompleteAuthentication\n let securityQuestionPayload = this.toolbox.breakSecretIntoShards(\n recoverySecurityQuestions,\n recoverySecurityAnswers,\n this.rsa.private(),\n threshold\n )\n let updateRequest = {\n recoverySecurityQuestions: securityQuestionPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the payload encrypted payload and updates the password itself (double hash)\n * @important\n * the recovery payload uses a singly hashed password and the password stored is doubly hashed so\n * the stored password cannot derive the decryption key in the payload\n * @note\n * the old password must be provided when not performing an account recovery\n * @param id\n * @param newPassword\n * @param oldPassword\n */\n public async updatePassword(id: Uuid, newPassword: string, oldPassword?: string) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(newPassword)\n let passwordPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n if (oldPassword) {\n oldPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(oldPassword))\n }\n\n newPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(newPassword))\n\n let updateRequest = {\n password: {\n oldPassword,\n newPassword,\n },\n recoveryPassword: passwordPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the master key encrypted payload\n * Important\n * Since the master key is used to generate a payload for the private key, it will never be stored on the device as it must remain secret!\n * @param id\n * @param masterKey\n * @param lockboxUuid\n */\n async updateMasterKey(id: Uuid, masterKey: string, lockboxUuid: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let masterKeyPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n let updateRequest = { recoveryMasterKey: masterKeyPayload }\n const updatedIdentity = await this.guardClient.identityUpdate(id, updateRequest)\n\n await this.getOrInsertJsonData<RecoveryMeta>(\n lockboxUuid,\n { masterKey },\n {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n },\n {},\n true\n )\n\n return updatedIdentity\n }\n}\n","import { AxiosService, CliniaResponse, FacetFilter, PlaceData } from \"oro-sdk-apis\"\n\nexport class CliniaService {\n private api: AxiosService\n\n constructor(private url: string, apiKey: string, private locale?: string) {\n this.api = new AxiosService({ headers: { 'X-Clinia-API-Key': apiKey } })\n }\n\n public placeSearch(searchOptions: {\n locale?: string\n query?: string\n facetFilters?: FacetFilter[]\n location?: string\n aroundLatLng?: string\n page?: number\n }) {\n const { locale, ...data } = searchOptions\n\n return this.api.post<CliniaResponse<PlaceData>>(\n `${this.url}/search/v1/indexes/health_facility/query`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n }\n\n public placeMatch(\n searchOptions: {\n locale?: string\n name?: string\n address?: string\n postalCode?: string\n place?: string\n region?: string\n country?: string\n },\n type?: string\n ) {\n const { locale, ...data } = searchOptions\n\n let request = this.api.post<PlaceData[]>(\n `${this.url}/search/v1/matches`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n\n if (type) {\n request = request.then((places) =>\n places.filter((place) => place.type === type)\n )\n }\n\n return request\n }\n}\n","import initApis from 'oro-sdk-apis'\nimport { OroClient } from './client'\nimport * as OroToolboxNamespace from 'oro-toolbox'\n\nexport type OroToolbox = typeof OroToolboxNamespace\n\nexport let wasmPath = 'node_modules/oro-toolbox'\n\n/**\n * This function helps you to initialize and OroClient instance\n * @param toolbox the OroToolbox object\n * @param tellerBaseURL the teller service base URL \n * @param vaultBaseURL the vault service base URL \n * @param guardBaseURL the guard service base URL \n * @param searchbaseURL the search service base URL\n * @param practiceBaseURL the practice service base URL \n * @param consultBaseURL the consult service base URL \n * @param workflowBaseURL the workflow service base URL \n * @param diagnosisBaseURL the diagnosis service base URL \n * @param authenticationCallback (optional) authenticationCallback the authentification callback \n * @returns an instance of OroClient\n */\nconst init = (\n toolbox: OroToolbox,\n tellerBaseURL: string,\n vaultBaseURL: string,\n guardBaseURL: string,\n searchBaseURL: string,\n practiceBaseURL: string,\n consultBaseURL: string,\n workflowBaseURL: string,\n diagnosisBaseURL: string,\n authenticationCallback?: (err: Error) => void\n) => {\n const {\n tellerService,\n practiceService,\n consultService,\n vaultService,\n guardService,\n searchService,\n workflowService,\n diagnosisService,\n } = initApis(\n {\n tellerBaseURL,\n vaultBaseURL,\n guardBaseURL,\n searchBaseURL,\n practiceBaseURL,\n consultBaseURL,\n workflowBaseURL,\n diagnosisBaseURL,\n },\n authenticationCallback\n )\n\n const client = new OroClient(\n toolbox,\n tellerService!,\n vaultService!,\n guardService!,\n searchService!,\n practiceService!,\n consultService!,\n workflowService!,\n diagnosisService!,\n authenticationCallback\n )\n\n return client\n}\n\nexport { OroClient } from './client'\nexport * from 'oro-sdk-apis'\nexport * from './models'\nexport * from './helpers'\nexport * from './services'\nexport { OroToolboxNamespace }\nexport default init\n"],"names":["personalMetaToPrefix","MetadataCategory","Personal","ChildPersonal","OtherPersonal","identificationToPersonalInformations","data","category","prefix","birthday","firstname","gender","name","phone","zip","hid","pharmacy","address","toActualObject","ret","Object","entries","fields","forEach","field","displayedAnswer","answer","sessionStorePrivateKeyName","id","IncompleteAuthentication","_inheritsLoose","Error","MissingGrant","MissingGrantFilter","MissingLockbox","MissingLockboxOwner","AssociatedLockboxNotFound","WorkflowAnswersMissingError","filterTriggeredAnsweredWithKind","workflowData","kind","selectedAnswers","_context","flattenedAnswers","flattenSelectedAnswers","triggeredQuestionsWithKind","fromEntries","pages","map","a","questions","filter","question","isTriggered","triggers","flat","samePageAnswers","reduce","prev","cur","res","keys","questionFieldName","getWorkflowDataByCategory","_context2","triggeredQuestions","Promise","all","e","k","populateWorkflowField","then","populatedValue","workflowCreatedAt","createdAt","workflowId","locale","err","console","error","getImagesFromIndexDb","_context3","getMany","v","answerValue","undefined","_context4","answers","text","value","images","image","imageData","resolve","includes","Array","isArray","some","subSetTriggers","every","trigger","linearAnswers","push","values","getInitialisedSelectedAnswers","workflow","useDefault","page","defaultValue","registerPatient","patientUuid","consultRequest","oroClient","masterKey","recoveryQA","indexSearch","onProgress","consult","lockboxUuid","practitionerAdmin","retry","identity","errorsThrown","stepsTotalNum","currentStep","setTimeout","practiceClient","practiceGetFromUuid","uuidPractice","uuidAdmin","practiceGetPractitioners","log","practitioners","getOrCreatePatientConsultationUuid","getOrCreatePatientLockbox","guardClient","identityGet","grantLockbox","grantPromises","practitioner","uuid","IndexKey","ConsultationLockbox","grant","lockboxOwnerUuid","consultationId","consultIndex","consultIndexPromises","vaultIndexAdd","storeImageAliases","storePatientData","isoLanguageRequired","_identity","recoveryMasterKey","updateMasterKey","_identity2","recoverySecurityQuestions","updateSecurityQuestions","recoverySecurityAnswers","buildConsultSearchIndex","length","consultClient","updateConsultByUUID","statusMedical","MedicalStatus","New","cleanIndex","_context5","practiceGetPayment","idStripeInvoiceOrPaymentIntent","payment","uuidConsult","getConsultByUUID","consultCreate","_context6","getGrants","grants","vaultClient","lockboxCreate","lockboxResponse","authRefresh","tokens","setTokens","accessToken","refreshToken","whoAmI","isoLanguage","getOrInsertJsonData","Raw","contentType","Consultation","documentType","DocumentType","PopulatedWorkflowData","Medical","consultationIds","extractAndStorePersonalWorkflowData","Preference","dataUuids","progress","_context8","nonNullImages","img","storedImagesNum","totalImagesNum","promises","ImageAlias","idbId","progressStepValue","Math","round","extractPersonalInfoFromWorkflowData","personalInfoPopulatedWfData","childPersonalInfoPopulatedWfData","otherPersonalInfoPopulatedWfData","terms","shortId","_context11","_yield$extractPersona","personalInfo","childPersonalInfo","otherPersonalInfo","searchClient","index","decryptGrants","encryptedGrants","rsaKey","encryptedLockbox","uuidParse","base64DecryptToBytes","decryptConsultLockboxGrants","encryptedConsultLockboxes","base64DecryptToJson","encryptedIndexEntry","grantsTuple","grantTuples","filterGrantsWithLockboxMetadata","filteredGrants","_iterator","lockboxMetadataGet","OroClient","toolbox","tellerClient","workflowClient","diagnosisClient","authenticationCallback","this","_proto","cachedMetadataGrants","cachedManifest","signUp","email","password","practice","tosAndCpAcceptance","tokenData","subscription","skipEmailValidation","rsa","CryptoRSA","privateKey","symmetricEncryptor","CryptoChaCha","fromPassphrase","recoveryPassword","bytesEncryptToBase64Payload","hashedPassword","hashStringToBase64","emailConfirmed","signupRequest","practiceUuid","toLowerCase","publicKey","encodeToBase64","identityCreate","recoveryLogin","symetricEncryptor","sessionStorage","setItem","confirmEmail","identityUpdate","sub","signIn","otp","tokenRequest","authToken","userUuid","recoverPrivateKeyFromPassword","resumeSession","recoveryPayload","getItem","recoveryKey","symmetricDecryptor","base64PayloadDecryptToBytes","fromKey","localEncryptToJsonPayload","chaChaKey","encryptedData","jsonEncryptToBase64Payload","encryptedKey","encryptToBytes","key","localDecryptJsonPayload","base64PayloadDecryptToJson","signOut","secrets","authLogout","_context7","forceUpdateIndexEntries","_context9","_this","consults","alert","indexOwnerUuid","_context10","rsaPub","decodeFromBase64","encryptedIndex","_i","uniqueHash","timestamp","jsonWithPubEncryptToBase64","vaultIndexPut","granteeUuid","getCachedSecretCryptor","secret","granteePublicKey","granteeEncryptedSecret","bytesWithPubEncryptToBase64","request","encryptedSecret","lockboxGrant","createMessageData","message","previousDataUuid","_context12","author","encryptedPrivateMeta","lockboxDataStore","publicMetadata","Message","privateMetadata","createMessageAttachmentData","_context13","Uint8Array","arrayBuffer","lastModified","size","fileName","type","createConsultationAttachmentData","withNotification","_context14","createBytesData","createJsonData","meta","privateMeta","_context15","forceReplace","_context16","lockboxManifestGet","manifest","JSON","stringify","dataUuid","_context17","getJsonData","_context18","lockboxDataGet","_yield$Promise$all","getBytesData","_context19","_yield$Promise$all2","_context20","filterString","getAccountRole","currentAccountRole","OtherRoleType","User","Patient","requiredRole","grantsGet","decryptedGrants","info","vaultIndexGet","decryptedConsults","grantsByConsultLockbox","_context21","scope","split","_context22","findIndex","lockboxSecretGet","sharedSecret","cryptor","getPersonalInformationsFromConsultId","forceRefresh","getMetaCategoryFromConsultId","getMedicalDataFromConsultId","_context27","_loop","_context26","_this2","getLockboxManifest","entry","metadata","_context25","getPersonalInformations","userId","_context28","find","lockbox","identificationDataUuid","getGrantFromConsultId","_context29","getIdentityFromConsultId","_context30","expandPrivateMetadata","manifestKey","_context32","_context31","_this3","createPersonalInformations","_context33","_yield$this$getGrants","createUserPreference","preference","_context34","_yield$this$getGrants2","getDataFromGrant","_context35","getUserPreferenceFromConsultId","_context36","getUserPreference","_context37","getRecoveryDataFromConsultId","_context38","Recovery","getRecoveryData","_context39","getAssignedConsultations","_context41","_this4","_context40","promise","getPastConsultationsFromConsultId","_context43","consultationsInLockbox","consultId","_context42","_this5","getPatientConsultationData","_context44","_this6","getPatientPrescriptionsList","getPatientDocumentsList","Prescription","getPatientResultsList","Result","getPatientTreatmentPlans","TreatmentPlan","getPatientTreatmentPlanByUuid","treatmentPlanId","filters","_context50","_this7","recoverPrivateKeyFromSecurityQuestions","threshold","_context51","answeredShards","shard","indexOfQuestion","indexOf","securityQuestion","item","securityAnswer","reconstructSecret","_context52","recoverPrivateKeyFromMasterKey","_context53","_context54","securityQuestionPayload","breakSecretIntoShards","updateRequest","updatePassword","newPassword","oldPassword","_context55","passwordPayload","_context56","masterKeyPayload","updatedIdentity","CliniaService","url","apiKey","api","AxiosService","headers","X-Clinia-API-Key","placeSearch","searchOptions","post","params","placeMatch","places","place","tellerBaseURL","vaultBaseURL","guardBaseURL","searchBaseURL","practiceBaseURL","consultBaseURL","workflowBaseURL","diagnosisBaseURL","initApis","tellerService","vaultService","guardService","searchService","practiceService","consultService","workflowService","diagnosisService","arrSelectedLocality","flatMap","currentAnswerPage","arrCountryFields","workflowFieldName","arrProvinceFields","arrConsultLocalFields","currentFieldName","currentSelectedLocality","startsWith","allowedLocalityPatterns","indexPriority","isoValue","finalLocality","extractedSelected","exec","indexSelectedPriority","isoSelectedValue","extractedFinal","indexFinalPriority","populatedWorkflow","filledWorkflow","parse","pageIdx","infos"],"mappings":"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"}
1
+ {"version":3,"file":"oro-sdk.cjs.production.min.js","sources":["../src/helpers/client.ts","../src/models/error.ts","../src/helpers/workflow.ts","../src/helpers/consult.ts","../src/helpers/patient-registration.ts","../src/helpers/vault-grants.ts","../src/helpers/prescription-refill.ts","../src/sdk-revision/client.ts","../src/client.ts","../src/services/external/clinia.ts","../src/index.ts"],"sourcesContent":["import {\n PopulatedWorkflowData,\n MetadataCategory,\n SelectedAnswersData,\n} from 'oro-sdk-apis'\nimport { PersonalInformations } from '../models/client'\n\nconst personalMetaToPrefix = {\n [MetadataCategory.Personal]: 'you',\n [MetadataCategory.ChildPersonal]: 'child',\n [MetadataCategory.OtherPersonal]: 'other',\n}\n\n/**\n * This function extract PersonalInformations from data input object coming from workflow\n * @param data extracted from WorkflowData\n * @returns PersonalInformations of a patient\n */\nexport function identificationToPersonalInformations(\n data: any,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n): PersonalInformations {\n const prefix = personalMetaToPrefix[category]\n\n return {\n birthday: data[`${prefix}Birthday`],\n firstname: data[`${prefix}Firstname`],\n gender: data[`${prefix}Gender`],\n name: data[`${prefix}Name`],\n phone: data[`${prefix}Phone`],\n zip: data[`${prefix}Zip`],\n hid: data[`${prefix}HID`] ?? data[`${prefix}ID`], // This is done for backward compatibility (historically youID was used)\n pharmacy: data[`${prefix}Pharmacy`],\n address: data[`${prefix}Address`],\n }\n}\n\nexport function toActualObject(data: PopulatedWorkflowData) {\n const ret: any = {}\n\n Object.entries(data.fields).forEach(([key, field]) => {\n ret[key] = field.displayedAnswer ? field.displayedAnswer : field.answer\n })\n\n return ret\n}\n\n/**\n * This function update a PopulatedWorkflowData with PersonalInformations\n * @param infos the personal informations\n * @param data the PopulatedWorkflowData\n * @returns an updated PopulatedWorkflowData\n */\nexport function updatePersonalIntoPopulatedWorkflowData(\n infos: PersonalInformations,\n data: PopulatedWorkflowData,\n category:\n | MetadataCategory.Personal\n | MetadataCategory.ChildPersonal\n | MetadataCategory.OtherPersonal\n) {\n const prefix = personalMetaToPrefix[category]\n\n const ret = JSON.parse(JSON.stringify(data)) // deep copy PopulatedWorkflowData\n\n if (infos.birthday && ret.fields[`${prefix}Birthday`])\n ret.fields[`${prefix}Birthday`].answer = infos.birthday\n if (infos.firstname && ret.fields[`${prefix}Firstname`])\n ret.fields[`${prefix}Firstname`].answer = infos.firstname\n if (infos.gender && ret.fields[`${prefix}Gender`])\n ret.fields[`${prefix}Gender`].answer = infos.gender\n if (infos.name && ret.fields[`${prefix}Name`])\n ret.fields[`${prefix}Name`].answer = infos.name\n if (infos.phone && ret.fields[`${prefix}Phone`])\n ret.fields[`${prefix}Phone`].answer = infos.phone\n if (infos.zip && ret.fields[`${prefix}Zip`])\n ret.fields[`${prefix}Zip`].answer = infos.zip\n if (infos.hid) {\n if (ret.fields[`${prefix}HID`]) {\n ret.fields[`${prefix}HID`].answer = infos.hid\n } else if (ret.fields[`${prefix}ID`]) {\n // This is done for backward compatibility (historically youID was used)\n ret.fields[`${prefix}ID`].answer = infos.hid\n } else {\n // If does not exist create it\n ret.fields[`${prefix}HID`] = { kind: 'text', answer: infos.hid }\n }\n }\n\n return ret\n}\n\n/**\n * This function extract an ISO 3166-1 alpha-2 country and subdivision code from data input object coming from workflow\n * @param answers answers from the WorkflowData\n * @returns an ISO 3166 alpha-2 code or undefined\n */\nexport function extractISOLocalityForConsult(\n answers?: SelectedAnswersData\n): string | undefined {\n if (!answers) {\n return undefined\n }\n\n const arrAnswersWithLocality = answers\n .flatMap((currentAnswerPage) => {\n const arrCountryFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Country') !== -1\n )\n .flat()\n const arrProvinceFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Province') !== -1\n )\n .flat()\n const arrConsultLocalFields = Object.keys(currentAnswerPage)\n .filter(\n (workflowFieldName) =>\n workflowFieldName.indexOf('Locality') !== -1\n )\n .flat()\n //returning the actual selected values, skipping if their IDs are more complex than a string\n return [\n ...arrCountryFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrProvinceFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ...arrConsultLocalFields.map(\n (currentFieldName) =>\n (typeof currentAnswerPage[currentFieldName] === 'string'\n ? currentAnswerPage[currentFieldName]\n : undefined) as string\n ),\n ]\n })\n .filter((item) => item !== undefined)\n\n const arrSelectedLocality = arrAnswersWithLocality.filter(\n (currentSelectedLocality) =>\n currentSelectedLocality.startsWith('isoLocalityConsult')\n )\n if (!arrSelectedLocality || arrSelectedLocality.length === 0) {\n console.log('no locality found in ' + arrSelectedLocality)\n return undefined\n }\n //to allow enforcing of an order, we will allow the following pattern in the isoLocalityConsult field name\n // isoLocalityConsult-QC-CA and isoLocalityConsult_1-QC-CA\n // or generally: isoLocalityConsult-<isoValue> or isoLocalityConsult_<priority>-<isoValue>\n const allowedLocalityPatterns = /isoLocalityConsult(?:_(?<indexPriority>\\d*))?-(?<isoValue>[a-zA-Z0-9]{2}-[a-zA-Z0-9]{1,3})/\n const finalLocality = arrSelectedLocality.reduce<string | undefined>(\n (finalLocality, currentSelectedLocality) => {\n const extractedSelected = allowedLocalityPatterns.exec(\n currentSelectedLocality\n )\n const [, indexSelectedPriority, isoSelectedValue] =\n extractedSelected ?? []\n if (!finalLocality) {\n return isoSelectedValue\n }\n\n const extractedFinal = allowedLocalityPatterns.exec(finalLocality)\n const [, indexFinalPriority, isoFinalValue] = extractedFinal ?? []\n //we only keep the old value if there's priority used\n // and the new value is of lower priority\n if (\n !indexSelectedPriority ||\n (indexFinalPriority &&\n indexFinalPriority > indexSelectedPriority)\n ) {\n return isoFinalValue\n }\n\n return isoSelectedValue\n },\n undefined\n )\n\n console.log('Picking locality ' + finalLocality)\n return finalLocality\n}\n\nconst sessionPrivateKeyPrefix = 'sess-pkey'\nexport function sessionStorePrivateKeyName(id: string): string {\n return sessionPrivateKeyPrefix + id\n}\n","export class IncompleteAuthentication extends Error { }\nexport class MissingGrant extends Error { }\nexport class MissingGrantFilter extends Error { }\nexport class MissingLockbox extends Error { }\nexport class MissingLockboxOwner extends Error { }\nexport class AssociatedLockboxNotFound extends Error { }\nexport class WorkflowAnswersMissingError extends Error { }\n","import { getMany } from 'idb-keyval'\nimport { WorkflowAnswersMissingError } from '../models'\nimport {\n MetadataCategory,\n PopulatedWorkflowData,\n PopulatedWorkflowField,\n QuestionData,\n SelectedAnswerData,\n SelectedAnswersData,\n WorkflowData,\n WorkflowPageData,\n WorkflowUploadedImage,\n} from 'oro-sdk-apis'\n\nexport async function filterTriggeredAnsweredWithKind(\n workflowData: WorkflowData,\n kind:\n | 'text'\n | 'text-area'\n | 'text-select-group'\n | 'date'\n | 'number'\n | 'images'\n | 'images-alias'\n | 'body-parts'\n | 'pharmacy-picker'\n | 'online-pharmacy-picker'\n | 'hair-selector-women'\n | 'hair-selector-men'\n | 'hair-loss-stage'\n | 'hair-loss-frontal'\n): Promise<SelectedAnswerData[]> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestionsWithKind = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(\n ([_, question]) => isTriggered(question.triggers || [], flattenedAnswers) && question.kind === kind\n )\n })\n .flat()\n )\n\n const samePageAnswers = workflowData.selectedAnswers.reduce((prev, cur) => {\n return { ...prev, ...cur }\n }, {})\n\n const res = Object.keys(triggeredQuestionsWithKind).map((questionFieldName) => {\n return samePageAnswers[questionFieldName]\n })\n\n return res\n}\n\n/**\n * Filters and Populates the `selectedAnswers` from the workflow by\n * Cross-referencing the `MetaCategory` of the answer's respective question\n * Populates the fields labels and values that are of radio, dropdown and checkbox types\n *\n * @param workflowData\n * @param category\n * @returns An array of record key, value pairs\n */\nexport async function getWorkflowDataByCategory(\n workflowData: WorkflowData,\n category: MetadataCategory\n): Promise<PopulatedWorkflowData> {\n if (!workflowData.selectedAnswers) throw WorkflowAnswersMissingError\n\n // Flattens the list of answered questions\n let flattenedAnswers = flattenSelectedAnswers(workflowData.selectedAnswers)\n // Generates a list of applicable questions\n let triggeredQuestions = Object.fromEntries(\n workflowData.pages\n .map((a) => {\n return Object.entries(a.questions).filter(([_, question]) =>\n isTriggered(question.triggers || [], flattenedAnswers)\n )\n })\n .flat()\n )\n\n const fields: Record<string, PopulatedWorkflowField> = {}\n\n // Generates the answers of the specified category and adds the appropriate values if any are missing\n return Promise.all(\n workflowData.selectedAnswers\n .map((e) => Object.entries(e))\n .flat()\n .filter(([k, v]) => triggeredQuestions[k] && triggeredQuestions[k]['metaCategory'] === category)\n .map(([k, v]) => {\n return populateWorkflowField(triggeredQuestions[k], v).then((populatedValue) => {\n fields[k] = populatedValue\n })\n })\n )\n .then(() => {\n const ret: PopulatedWorkflowData = {\n workflowCreatedAt: workflowData.createdAt,\n workflowId: workflowData.id,\n locale: workflowData.locale,\n fields,\n }\n return ret\n })\n .catch((err) => {\n console.error(`Error while extracting ${category} data from workflow`, err)\n throw err\n })\n}\n\nexport async function getImagesFromIndexDb(answer: SelectedAnswerData): Promise<WorkflowUploadedImage[]> {\n return await getMany<WorkflowUploadedImage>((answer as any[]).map((v) => v.id ?? v) as string[])\n}\n\n/**\n * (If applicable) Based on the question kind, and the answer type this function will add and replace the appropriate fields to the\n * field values if they are radio, dropdown and checkbox fields\n *\n *\n * @param question\n * @param answerValue\n * @returns\n */\nasync function populateWorkflowField(\n question: QuestionData,\n answerValue: SelectedAnswerData\n): Promise<PopulatedWorkflowField> {\n let answer: any\n let displayedAnswer: string | string[] | undefined = undefined\n switch (question.kind) {\n case 'text-select-group':\n if (question.answers) {\n displayedAnswer = `${answerValue[0]} ${question.answers[answerValue[1] as string].text}`\n }\n answer = answerValue\n break\n case 'radio':\n case 'radio-card':\n case 'select':\n if (question.answers) {\n displayedAnswer = question.answers[answerValue as string].text\n }\n\n answer = answerValue\n break\n case 'multiple':\n case 'checkbox-group':\n displayedAnswer = (answerValue as string[]).map((value) => {\n if (question.answers) {\n return question.answers[value].text\n }\n\n throw new WorkflowAnswersMissingError()\n })\n\n answer = answerValue\n break\n case 'images':\n answer = await getImagesFromIndexDb(answerValue).then((images) =>\n images.map((image) => {\n const { name, imageData } = image\n\n return { name, imageData }\n })\n )\n break\n default:\n answer = answerValue\n }\n\n return Promise.resolve({\n answer,\n displayedAnswer,\n kind: question.kind,\n })\n}\n\n/**\n * Determine if a question is triggered by some answers\n *\n * We use the following logical combinations of rules:\n *\n * #### Single string\n *\n * ```\n * // Required: rule1\n * rules: rule1\n * ```\n *\n * #### Array of strings (AND is applied between statements):\n *\n * ```\n * // Required: rule1 AND rule2\n * rules: [ rule1, rule2 ]\n * ```\n *\n * #### Array of arrays of strings (OR is applied between inner arrays. AND is applied between inner arrays statements)\n *\n * ```\n * // Required: rule1 OR rule2\n * rules: [\n * [ rule1 ],\n * [ rule2 ]\n * ]\n *\n * // Required: rule1 OR (rule2 AND rule3)\n * rules: [\n * [ rule1 ],\n * [ rule2, rule3 ]\n * ]\n *\n * // THIS IS FORBIDDEN\n * rules: [\n * rule1, // <-- THIS IS FORBIDDEN. Instead use [ rule1 ]\n * [ rule2, rule3 ]\n * ]\n * ```\n *\n * @param triggers the triggering rules\n * @param answers the answers to check againts triggering rules\n * @returns `true` if triggers are verified against ansers. Otherwise, returns `false`.\n * @throws an Error if triggers typing is wrong\n */\nexport function isTriggered(triggers: string[][] | string[] | string, answers: string[]): boolean {\n // is triggers contained in answers\n if (typeof triggers === 'string') {\n return answers.includes(triggers)\n }\n\n if (Array.isArray(triggers)) {\n // rule combination kind: rule1 OR (rule2 AND rule3)\n if (Array.isArray(triggers[0])) {\n return (triggers as string[][]).some((subSetTriggers) =>\n subSetTriggers.every((trigger) => answers.includes(trigger))\n )\n } else {\n // rule combination kind: rule1 AND rule2\n return (triggers as string[]).every((trigger) => answers.includes(trigger))\n }\n }\n\n throw Error('[isTriggered] triggers is not typed well')\n}\n\nexport function flattenSelectedAnswers(answers: SelectedAnswersData) {\n const linearAnswers: SelectedAnswerData[] = []\n\n for (const answer of answers) {\n linearAnswers.push(...Object.values(answer))\n }\n\n return linearAnswers.flat(1)\n}\n\n/**\n * This function helps you to get a valid workflow selectedAnswers structure\n * @param workflow the workflow data to use to initialize selectedAnswers\n * @param useDefault use workflow default values or not (this is used to avoid having unset values to appear in summaries)\n * @returns a valid selectedAnswers structure\n */\nexport function getInitialisedSelectedAnswers(workflow: WorkflowData, useDefault: boolean = true) {\n return workflow.pages.map((page) => {\n const ret: any = {}\n for (const [id, question] of Object.entries(page.questions)) {\n if (question.kind === 'body-parts') {\n ret[id] = useDefault ? [] : undefined\n } else {\n ret[id] = useDefault && question.defaultValue ? question.defaultValue : undefined\n }\n }\n return ret\n })\n}\n\nexport function fillWorkflowFromPopulatedWorkflow(workflow: WorkflowData, populatedWorkflow: PopulatedWorkflowData) {\n const filledWorkflow = JSON.parse(JSON.stringify(workflow))\n\n if (!filledWorkflow.selectedAnswers) {\n filledWorkflow.selectedAnswers = getInitialisedSelectedAnswers(filledWorkflow, false)\n }\n\n filledWorkflow.pages.forEach((page: WorkflowPageData, pageIdx: number) => {\n const ret: any = {}\n for (const [id] of Object.entries(page.questions)) {\n if (populatedWorkflow.fields[id]) {\n if (filledWorkflow.selectedAnswers)\n filledWorkflow.selectedAnswers[pageIdx][id] = populatedWorkflow.fields[id].answer as\n | string\n | string[]\n }\n }\n })\n\n return filledWorkflow\n}\n","import { Consult, ConsultRequest } from 'oro-sdk-apis'\nimport { OroClient } from '..'\n\n/**\n * Creates a consultation if one has not been created and fails to be retrieved by the payment intent\n * @param consult\n * @param oroClient\n * @returns the consult Uuid\n */\nexport async function getOrCreatePatientConsultationUuid(\n consult: ConsultRequest,\n oroClient: OroClient\n): Promise<Consult> {\n let payment = await oroClient.practiceClient.practiceGetPayment(\n consult.uuidPractice,\n consult.idStripeInvoiceOrPaymentIntent\n )\n if (payment && payment.uuidConsult) {\n return oroClient.consultClient.getConsultByUUID(payment.uuidConsult).catch((err) => {\n console.error('Error while retrieving consult', err)\n throw err\n })\n } else {\n return await oroClient.consultClient.consultCreate(consult).catch((err) => {\n console.error('Error while creating consult', err)\n throw err\n })\n }\n}\n","import {\n Consult,\n ConsultationImageMeta,\n ConsultationMeta,\n ConsultRequest,\n DocumentType,\n IdentityResponse,\n IndexKey,\n MedicalMeta,\n MedicalStatus,\n MetadataCategory,\n PersonalMeta,\n PopulatedWorkflowData,\n Practitioner,\n PreferenceMeta,\n RawConsultationMeta,\n Term,\n Terms,\n Uuid,\n VaultIndex,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport {\n filterTriggeredAnsweredWithKind,\n getImagesFromIndexDb,\n getWorkflowDataByCategory,\n identificationToPersonalInformations,\n OroClient,\n RegisterPatientOutput,\n toActualObject,\n} from '..'\nimport { getOrCreatePatientConsultationUuid } from './consult'\n\nconst MAX_RETRIES = 15\n\n/**\n * Completes a registration for a user retrying the complete flow a maximum of 15 times\n *\n * @description The order of importance when registering:\n * Creates a consultation if none exist\n * Retrieves or create's a lockbox if none exist\n * Grants the lockbox (if new) to all practitioners in the practice\n * Stores or fetches the patient data (without images)\n * Indexes the lockbox to the consult for all practitioners (done after inserting since index can be rebuilt from grants)\n * Stores the image data - done last since the majority of failure cases occur here\n * Creates the recovery payloads if they don't exist\n *\n * @param patientUuid\n * @param consultRequest\n * @param workflow\n * @param oroClient\n * @param masterKey\n * @param recoveryQA\n * @param indexSearch create search index for the consultation if true\n * @param onProgress callback that is called whenever a new step of patient registration is executed. Note: progress ranges from 0 to 1, and descriptionKey is a description of the progress as a key so the app would use it to translate the description\n * @returns the successful registration\n */\nexport async function registerPatient(\n patientUuid: Uuid,\n consultRequest: ConsultRequest,\n workflow: WorkflowData,\n oroClient: OroClient,\n masterKey?: Uuid,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n },\n indexSearch: boolean = true,\n onProgress?: (\n progress: number,\n descriptionKey: string,\n extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }\n ) => void\n): Promise<RegisterPatientOutput> {\n let consult: Consult | undefined = undefined\n let lockboxUuid: Uuid | undefined = undefined\n let practitionerAdmin: Uuid | undefined = undefined\n let retry = MAX_RETRIES\n let identity: IdentityResponse | undefined = undefined\n let errorsThrown: Error[] = []\n const stepsTotalNum = 9\n let currentStep: number\n\n for (; retry > 0; retry--) {\n try {\n currentStep = 0\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'retrieve_practitioners')\n\n // Wait a bit each retry (we also want the first one to wait)\n await new Promise((resolve) => setTimeout(resolve, 2000))\n\n // Retrieving practitioners\n if (!practitionerAdmin)\n practitionerAdmin = (await oroClient.practiceClient.practiceGetFromUuid(consultRequest.uuidPractice))\n .uuidAdmin\n\n let practitioners: Practitioner[] = await oroClient.practiceClient\n .practiceGetPractitioners(consultRequest.uuidPractice)\n .catch((err) => {\n console.log(`Error retrieving practitioners`, err)\n return []\n })\n\n // Creating consult\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_consult')\n\n if (!consult) {\n consult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n }\n\n // Creating lockbox\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'create_lockbox')\n\n if (!lockboxUuid) lockboxUuid = await getOrCreatePatientLockbox(oroClient)\n\n if (!identity) identity = await oroClient.guardClient.identityGet(patientUuid)\n\n await oroClient.grantLockbox(practitionerAdmin, lockboxUuid).catch((err) => {\n console.error(`Error while granting lockbox to practitioner admin ${practitionerAdmin}`, err)\n // if we cannot grant to the admin, then the registration will fail\n errorsThrown.push(err)\n })\n\n // Patient Grant to practice\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'grant_patient')\n\n let grantPromises = practitioners\n .filter((practitioner) => practitioner.uuid !== practitionerAdmin)\n .map(async (practitioner) => {\n return oroClient.grantLockbox(practitioner.uuid, lockboxUuid!).catch((err) => {\n console.error(`Error while granting lockbox to practitioner`, err)\n // Acceptable to continue as admin has already been granted, but we should still retry until the last retry remains\n if (retry <= 1) return\n errorsThrown.push(err)\n })\n })\n\n const consultIndex: VaultIndex = {\n [IndexKey.ConsultationLockbox]: [\n {\n grant: {\n lockboxUuid,\n lockboxOwnerUuid: patientUuid,\n },\n consultationId: consult.uuid,\n },\n ],\n }\n\n // the index will identify in which lockbox a consultation resides\n let consultIndexPromises = practitioners.map(async (practitioner) => {\n return oroClient.vaultIndexAdd(consultIndex, practitioner.uuid).catch((err) => {\n console.error(\n `[SDK: registration] Error while adding to the practitioner's index ${practitioner.uuid}`,\n err\n )\n // Acceptable to continue as the index can be rebuilt, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n })\n\n await storeImageAliases(\n consult.uuid,\n lockboxUuid,\n workflow,\n oroClient,\n onProgress\n ? {\n onProgress,\n currentStep,\n stepsTotalNum,\n }\n : undefined\n ).catch((err) => {\n console.error('[SDK: registration] Some errors happened during image upload', err)\n // Acceptable to continue as images can be requested during the consultation, but we should still retry until the last retry remains\n if (retry <= 1) return\n else errorsThrown.push(err)\n })\n ++currentStep\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'store_patient_data')\n\n await storePatientData(\n consult.uuid,\n consultRequest.isoLanguageRequired,\n lockboxUuid,\n workflow,\n oroClient\n ).catch((err) => {\n console.error('[SDK: registration] Some errors happened during patient data upload', err)\n errorsThrown.push(err)\n })\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_masterkey')\n\n if (masterKey && !identity?.recoveryMasterKey) {\n // generate and store recovery payload and updates the identity\n identity = await oroClient.updateMasterKey(patientUuid, masterKey, lockboxUuid).catch((err) => {\n console.error(`[SDK: registration] Error while updating master key`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n } else {\n // we did not set the master key so we do not return it\n masterKey = undefined\n }\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'set_security_questions')\n\n if (recoveryQA && !identity?.recoverySecurityQuestions)\n // Patient security question recovery threshold is 2 answers and updates the identity\n identity = await oroClient\n .updateSecurityQuestions(\n patientUuid,\n recoveryQA.recoverySecurityQuestions,\n recoveryQA.recoverySecurityAnswers,\n 2\n )\n .catch((err) => {\n console.error(`[SDK: registration] Error while updating security questions`, err)\n /// it's acceptable to continue registration (return old identity)\n if (retry <= 1) return\n errorsThrown.push(err)\n return identity\n })\n\n await Promise.all([...grantPromises, ...consultIndexPromises])\n\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'search_indexing')\n\n if (indexSearch) {\n await buildConsultSearchIndex(consult, workflow, oroClient).catch((err) => {\n console.error(\n '[SDK: registration] personal information not found or another error occured during search indexing',\n err\n )\n if (retry <= 1) return // this statement is to avoid failing the registration due to the failure in search indexing the consult, this practically implements a soft retry\n errorsThrown.push(err)\n })\n }\n\n if (errorsThrown.length > 0) throw errorsThrown\n\n // Deem the consultation as ready\n await oroClient.consultClient.updateConsultByUUID(consult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n\n // if we got through the complete flow, the registration succeeded\n if (onProgress) onProgress(currentStep++ / stepsTotalNum, 'success')\n\n break\n } catch (err) {\n console.error(`[SDK] Error occured during registration: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n\n if (retry <= 0) {\n console.error('[SDK] registration failed: MAX_RETRIES reached')\n throw 'RegistrationFailed'\n }\n\n console.log('Successfully Registered')\n await oroClient.cleanIndex()\n return {\n masterKey,\n consultationId: consult!.uuid,\n lockboxUuid: lockboxUuid!,\n }\n}\n\n/**\n * Creates a new lockbox for the patient if they do not have any, otherwise, use the first (and only one)\n * @param oroClient\n * @returns the lockbox Uuid\n */\nasync function getOrCreatePatientLockbox(oroClient: OroClient): Promise<Uuid> {\n let grants = await oroClient.getGrants()\n if (grants.length > 0) {\n console.log('The grant has already been created, skipping lockbox create step')\n return grants[0].lockboxUuid!\n } else {\n let lockboxResponse = await oroClient.vaultClient.lockboxCreate().catch((err) => {\n console.error('Error while creating lockbox', err)\n throw err\n })\n // Since the creation of a lockbox will change the scope of a user, we will force refresh the tokens\n let tokens = await oroClient.guardClient.authRefresh()\n await oroClient.guardClient.setTokens({ accessToken: tokens.accessToken, refreshToken: tokens.refreshToken })\n await oroClient.guardClient.whoAmI(true)\n\n return lockboxResponse.lockboxUuid\n }\n}\n\n/**\n * Store all patient related information into his/her lockbox\n * @param consultationId The consultation id\n * @param isoLanguage the prefered language of communication (ISO 639-3 https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes)\n * @param lockboxUuid the lockbox uuid to store data in\n * @param workflow the workflow used to extract informations\n * @param oroClient an oroClient instance\n * @returns\n */\nasync function storePatientData(\n consultationId: Uuid,\n isoLanguage: string,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient\n): Promise<(Uuid | void)[]> {\n // Create and store registration data\n return Promise.all([\n // Storing Raw data first\n oroClient.getOrInsertJsonData<RawConsultationMeta>(\n lockboxUuid,\n workflow,\n {\n category: MetadataCategory.Raw,\n contentType: 'application/json',\n consultationId,\n },\n {}\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Consultation).then((data) =>\n oroClient.getOrInsertJsonData<ConsultationMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, // TODO: deprecated. Will finally only be in privateMetadata\n },\n { consultationId },\n false,\n true // the only data that needs to include an email notification\n )\n ),\n getWorkflowDataByCategory(workflow, MetadataCategory.Medical).then((data) =>\n oroClient.getOrInsertJsonData<MedicalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Medical,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId!],\n },\n {}\n )\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.Personal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.ChildPersonal,\n oroClient\n ),\n extractAndStorePersonalWorkflowData(\n workflow,\n lockboxUuid,\n consultationId,\n MetadataCategory.OtherPersonal,\n oroClient\n ),\n oroClient.getOrInsertJsonData<PreferenceMeta>(\n lockboxUuid,\n { isoLanguage },\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {}\n ),\n ]).then((dataUuids) => dataUuids.flat())\n}\n\nasync function storeImageAliases(\n consultationId: Uuid,\n lockboxUuid: Uuid,\n workflow: WorkflowData,\n oroClient: OroClient,\n progress?: {\n currentStep: number\n stepsTotalNum: number\n onProgress: (\n progress: number,\n descriptionKey: string,\n extraInfo?: { storedImagesNum?: number; totalImagesNum?: number }\n ) => void\n }\n): Promise<(Uuid | void)[]> {\n const images = await getImagesFromIndexDb((await filterTriggeredAnsweredWithKind(workflow, 'images-alias')).flat())\n\n const nonNullImages = images.filter((img) => !!img)\n\n if (images.length !== nonNullImages.length) {\n console.error('[SDK] Some images have not been found, they have been skipped.')\n }\n\n let storedImagesNum = 0\n let totalImagesNum = nonNullImages.length\n if (progress)\n progress.onProgress(progress.currentStep / progress.stepsTotalNum, 'store_images', {\n storedImagesNum,\n totalImagesNum,\n })\n\n let promises = nonNullImages.map((image) => {\n return oroClient\n .getOrInsertJsonData<ConsultationImageMeta>(\n lockboxUuid,\n image,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.ImageAlias,\n consultationId,\n idbId: image.idbId as string,\n },\n {}\n )\n .then(() => {\n if (progress) {\n ++storedImagesNum\n let progressStepValue =\n Math.round(\n ((progress.currentStep + 1) / progress.stepsTotalNum -\n progress.currentStep / progress.stepsTotalNum) *\n 100\n ) / 100\n progress.onProgress(\n progress.currentStep / progress.stepsTotalNum +\n progressStepValue * (storedImagesNum / totalImagesNum),\n 'store_images',\n {\n storedImagesNum,\n totalImagesNum,\n }\n )\n }\n })\n })\n return Promise.all(promises)\n}\n\n/**\n * Extracts the workflow MetadataCategory for Personal, ChildPersonal and OtherPersonal\n * then stores it in the vault\n *\n * @param workflow\n * @param lockboxUuid\n * @param category\n * @returns The data uuid\n */\nexport async function extractAndStorePersonalWorkflowData(\n workflow: WorkflowData,\n lockboxUuid: Uuid,\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n oroClient: OroClient\n): Promise<Uuid | void> {\n return getWorkflowDataByCategory(workflow, category as unknown as MetadataCategory).then((data) => {\n if (Object.keys(data.fields).length === 0) return\n return oroClient.getOrInsertJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n {}\n )\n })\n}\n\n/**\n * Given workflow data, it populates it with Personal, ChildPersonal, and OtherPersonal workflow data\n * @param workflow\n */\nexport async function extractPersonalInfoFromWorkflowData(workflow: WorkflowData): Promise<{\n personalInfoPopulatedWfData: PopulatedWorkflowData\n childPersonalInfoPopulatedWfData: PopulatedWorkflowData\n otherPersonalInfoPopulatedWfData: PopulatedWorkflowData\n}> {\n return Promise.all([\n getWorkflowDataByCategory(workflow, MetadataCategory.Personal),\n getWorkflowDataByCategory(workflow, MetadataCategory.ChildPersonal),\n getWorkflowDataByCategory(workflow, MetadataCategory.OtherPersonal),\n ]).then(([personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData]) => {\n return {\n personalInfoPopulatedWfData,\n childPersonalInfoPopulatedWfData,\n otherPersonalInfoPopulatedWfData,\n }\n })\n}\n\n/**\n * Creates the search index for the first name, last name, and the short id of the given consultation\n * @param consult the consultation to be search indexed\n * @param workflow the workflow data\n * @param oroClient\n */\nexport async function buildConsultSearchIndex(consult: Consult, workflow: WorkflowData, oroClient: OroClient) {\n let terms: Terms = [\n <Term>{\n kind: 'consult-shortid',\n value: consult.shortId,\n },\n ]\n\n const { personalInfoPopulatedWfData, childPersonalInfoPopulatedWfData, otherPersonalInfoPopulatedWfData } =\n await extractPersonalInfoFromWorkflowData(workflow)\n\n const personalInfo = identificationToPersonalInformations(\n toActualObject(personalInfoPopulatedWfData),\n MetadataCategory.Personal\n )\n const childPersonalInfo = identificationToPersonalInformations(\n toActualObject(childPersonalInfoPopulatedWfData),\n MetadataCategory.ChildPersonal\n )\n const otherPersonalInfo = identificationToPersonalInformations(\n toActualObject(otherPersonalInfoPopulatedWfData),\n MetadataCategory.OtherPersonal\n )\n\n terms.push(\n <Term>{\n kind: 'first-name',\n value: personalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: personalInfo.name,\n }\n )\n\n if (childPersonalInfo.firstname && childPersonalInfo.name) {\n terms.push(\n <Term>{\n kind: 'first-name',\n value: childPersonalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: childPersonalInfo.name,\n }\n )\n }\n\n if (otherPersonalInfo.firstname && otherPersonalInfo.name) {\n terms.push(\n <Term>{\n kind: 'first-name',\n value: otherPersonalInfo.firstname,\n },\n <Term>{\n kind: 'last-name',\n value: otherPersonalInfo.name,\n }\n )\n }\n\n await oroClient.searchClient.index(consult.uuid, terms)\n}\n","import { CryptoRSA, uuidParse} from \"oro-toolbox\"\nimport { EncryptedIndexEntry, Grant, IndexConsultLockbox } from \"oro-sdk-apis\"\n\n/**\n * Decrypts and returns the encrypted grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedGrants: an array of encrypted grants\n * @param rsaKey: the rsa key used to decrypt the encrypted grants\n * @returns an array of grants\n */\nexport function decryptGrants(encryptedGrants: Grant[], rsaKey: CryptoRSA): Grant[] {\n return encryptedGrants\n .map(grant => {\n if (grant.encryptedLockbox && !grant.lockboxUuid) {\n try {\n grant.lockboxUuid = uuidParse(\n rsaKey.base64DecryptToBytes(grant.encryptedLockbox)\n )\n } catch (e) {\n console.error('[sdk:index] The grant could not be decrypted or was not a valid UUID: ', e)\n }\n }\n return grant\n })\n .filter(grant => grant.lockboxUuid)\n}\n\n/**\n * Decrypts the encrypted consult lockboxes and returns their grants\n * If something went wrong during decryption, that grant will be removed from the list\n *\n * @param encryptedConsultLockboxes: an array of encrypted entries\n * @param rsaKey: the rsa key used to decrypt the encrypted entries\n * @returns an array of grants\n */\nexport function decryptConsultLockboxGrants(encryptedConsultLockboxes: EncryptedIndexEntry[], rsaKey: CryptoRSA): Grant[] {\n return encryptedConsultLockboxes\n .map(encryptedConsultLockboxes => {\n try {\n return [true, (rsaKey.base64DecryptToJson(\n encryptedConsultLockboxes.encryptedIndexEntry\n ) as IndexConsultLockbox).grant]\n } catch(e) {\n console.error('[sdk:index] The consult lockbox grant could not be decrypted: ', e)\n return [false, undefined] // if decryption fails, we want to ignore the grant but not fail the call\n }\n })\n .filter(grantsTuple => grantsTuple[0])\n .map(grantTuples => grantTuples[1] as Grant)\n}","import {\n Consult,\n ConsultRequest,\n DocumentType,\n MedicalStatus,\n MetadataCategory,\n PlaceData,\n SelectedAnswersData,\n Uuid,\n WorkflowData,\n} from 'oro-sdk-apis'\nimport { OroClient } from '..'\nimport { getOrCreatePatientConsultationUuid } from './consult'\n\nconst MAX_RETRIES = 15\n/**\n * Placeholder while the workflow interpreter for the refill flows is complete\n *\n * Creates a fake workflow in which the workflow data will reside\n *\n * @param isTreatmentWorking the value from the `is treatment working` question\n * @param hasSideEffects the value from the `does the treatment have side effects` question\n * @param deliveryAddress the provided delivery address\n * @param pharmacy\n * @returns a workflow\n */\nexport function getRefillAnswersAsWorkflow(\n isTreatmentWorking: string,\n hasSideEffects: string,\n deliveryAddress?: string,\n pharmacy?: PlaceData\n): WorkflowData {\n let selectedAnswers: SelectedAnswersData = [\n {\n ['isTreatmentWorking']: isTreatmentWorking,\n },\n {\n ['hasSideEffects']: hasSideEffects,\n },\n ]\n\n if (deliveryAddress) selectedAnswers.push({ ['deliveryAddress']: deliveryAddress })\n if (pharmacy) selectedAnswers.push({ ['pharmacy']: JSON.stringify(pharmacy) })\n\n return {\n \"id\": \"32573a20-6f1d-49be-9ad3-b87c58074979\",\n \"createdAt\": \"2022-10-03T00:00:00.000Z\",\n \"culDeSacs\": [],\n \"hidePlanRules\": [],\n \"pages\": [\n {\n \"title\": \"Prescription Refill\",\n \"groups\": [\n {\n \"type\": \"field-group\",\n \"fieldsAndGroups\": [\n {\n \"type\": \"field\",\n \"id\": \"isTreatmentWorking\"\n },\n {\n \"type\": \"field\",\n \"id\": \"hasSideEffects\"\n },\n {\n \"type\": \"field\",\n \"id\": \"youPharmacy\"\n },\n {\n \"type\": \"field\",\n \"id\": \"youAddress\"\n }\n ]\n }\n ],\n \"questions\": {\n \"isTreatmentWorking\": {\n \"label\": \"Is the treatment working for you?\",\n \"kind\": \"radio\",\n \"inline\": true,\n \"inlineLabel\": false,\n \"metaCategory\": MetadataCategory.Refill,\n \"answers\": {\n \"73bec6eb-0310-4787-af3c-ac9c291737b2\": {\n \"text\": \"Yes\"\n },\n \"e193951f-986f-4db3-bede-903045a1804a\": {\n \"text\": \"No\"\n }\n }\n },\n \"hasSideEffects\": {\n \"label\": \"Are there any side effects\",\n \"kind\": \"radio\",\n \"inline\": true,\n \"inlineLabel\": false,\n \"metaCategory\": MetadataCategory.Refill,\n \"answers\": {\n \"1b87ad22-d316-4fac-9c7f-8f4ccb841aed\": {\n \"text\": \"Yes\"\n },\n \"ab7f5a41-c351-4f5d-a568-e38f9f200e9a\": {\n \"text\": \"No\"\n }\n }\n },\n \"youPharmacy\": {\n \"kind\": \"online-pharmacy-picker\",\n \"label\": \"Which pharmacy do you want the prescription sent to?\",\n \"metaCategory\": MetadataCategory.Refill,\n \"minorLabel\": \" (Optional)\",\n \"summaryLabel\": \"Your pharmacy\"\n },\n \"youAddress\": {\n \"kind\": \"place-address\",\n \"label\": \"Address\",\n \"metaCategory\": MetadataCategory.Refill\n }\n }\n }\n ],\n \"locale\": \"en\",\n selectedAnswers\n }\n}\n\n/**\n * Complete refill flow, creates a consult, stores refill data and updates consultation status\n * @param consultRequest\n * @param populatedRefillWorkflow the refill workflow data\n * @param oroClient\n */\nexport async function createRefill(\n consultRequest: ConsultRequest,\n populatedRefillWorkflow: WorkflowData,\n oroClient: OroClient\n) {\n let retry = MAX_RETRIES\n let errorsThrown: Error[] = []\n\n let newConsult: Consult | undefined\n let lockboxUuid: Uuid | undefined\n\n for (; retry > 0; retry--) {\n try {\n if (!newConsult) newConsult = await getOrCreatePatientConsultationUuid(consultRequest, oroClient)\n\n if (!lockboxUuid) lockboxUuid = (await oroClient.getGrants())[0].lockboxUuid\n\n await oroClient\n .getOrInsertJsonData(\n lockboxUuid!,\n populatedRefillWorkflow,\n {\n category: MetadataCategory.Refill,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [newConsult.uuid],\n },\n {}\n )\n .catch((err) => {\n console.error('[SDK: prescription refill] Some errors happened during refill data upload', err)\n errorsThrown.push(err)\n })\n\n if (errorsThrown.length > 0) throw errorsThrown\n await oroClient.consultClient.updateConsultByUUID(newConsult.uuid, {\n statusMedical: MedicalStatus.New,\n })\n } catch (err) {\n console.error(`[SDK] Error occured during refill: ${err}, retrying... Retries remaining: ${retry}`)\n errorsThrown = []\n continue\n }\n }\n}\n","import { IndexKey, Grant, IndexConsultLockbox, MetadataCategory, VaultIndex } from 'oro-sdk-apis'\nimport { OroClient, Uuid } from '..'\n\n/**\n * @name filterGrantsWithLockboxMetadata\n * @description searches for the existance of a consult uuid in each granted lockbox\n * @param oroClient\n * @param filter: the consult uuid\n * @returns the grants containing the consult uuid\n */\nexport async function filterGrantsWithLockboxMetadata(\n oroClient: OroClient,\n filter: { consultationId: Uuid },\n): Promise<Grant[]> {\n let grants = await oroClient.getGrants()\n let filteredGrants = []\n for (let grant of grants) {\n // Fetches in each lockbox the existance of a given consult id\n let consultationIdExistsInMetadata = await oroClient.vaultClient.lockboxMetadataGet(grant.lockboxUuid!, ['consultationId'], [], {\n category: MetadataCategory.Consultation,\n consultationId: filter.consultationId\n })\n // If there are entries in the metadata, it means that the consult exists in the lockbox\n if (consultationIdExistsInMetadata[0].length >= 0)\n filteredGrants.push(grant)\n }\n\n return filteredGrants\n}\n","import {\n AllRoleType,\n AuthTokenRequest,\n Consult,\n ConsultRequest,\n ConsultService,\n DataCreateResponse,\n DiagnosisService,\n Document,\n DocumentType,\n EncryptedIndexEntry,\n EncryptedVaultIndex,\n Grant,\n GuardService,\n IdentityCreateRequest,\n IdentityResponse,\n IndexConsultLockbox,\n IndexKey,\n LocalizedData,\n LockboxDataRequest,\n LockboxGrantRequest,\n LockboxManifest,\n ManifestEntry,\n Meta,\n Metadata,\n MetadataCategory,\n OtherRoleType,\n PersonalMeta,\n PopulatedWorkflowData,\n Practice,\n PracticeService,\n PractitionnerRoleType,\n PreferenceMeta,\n RecoveryMeta,\n RoleBasedScopes,\n SearchService,\n SecretShard,\n TellerService,\n TokenData,\n TosAndCpAcceptanceRequest,\n Uuid,\n VaultIndex,\n VaultService,\n WorkflowData,\n WorkflowService,\n} from 'oro-sdk-apis'\nimport * as OroToolbox from 'oro-toolbox'\nimport { CryptoRSA } from 'oro-toolbox'\nimport {\n createRefill,\n decryptConsultLockboxGrants,\n decryptGrants,\n registerPatient,\n sessionStorePrivateKeyName,\n} from './helpers'\nimport {\n AssociatedLockboxNotFound,\n IncompleteAuthentication,\n LocalEncryptedData,\n MissingGrant,\n MissingGrantFilter,\n MissingLockbox,\n MissingLockboxOwner,\n RecoveryData,\n RegisterPatientOutput,\n UserPreference,\n} from './models'\nimport { filterGrantsWithLockboxMetadata } from './sdk-revision'\n\nexport class OroClient {\n private rsa?: CryptoRSA\n private secrets: {\n lockboxUuid: string\n cryptor: OroToolbox.CryptoChaCha\n }[] = []\n private cachedMetadataGrants: {\n [filter: string]: Grant[]\n } = {}\n\n private cachedManifest: {\n [filter: string]: ManifestEntry[]\n } = {}\n\n private vaultIndex?: VaultIndex\n\n constructor(\n private toolbox: typeof OroToolbox,\n public tellerClient: TellerService,\n public vaultClient: VaultService,\n public guardClient: GuardService,\n public searchClient: SearchService,\n public practiceClient: PracticeService,\n public consultClient: ConsultService,\n public workflowClient: WorkflowService,\n public diagnosisClient: DiagnosisService,\n private authenticationCallback?: (err: Error) => void\n ) {}\n\n /**\n * clears the vaultIndex and cached metadata grants\n */\n public async cleanIndex() {\n this.cachedMetadataGrants = {}\n this.cachedManifest = {}\n }\n\n /**\n * Generates an RSA key pair and password payload (rsa private key encrypted with the password)\n * Calls Guard to sign up with the email address, password, practice, legal and token data\n *\n * @param email\n * @param password\n * @param practice\n * @param legal\n * @param tokenData\n * @returns\n */\n public async signUp(\n email: string,\n password: string,\n practice: Practice,\n tosAndCpAcceptance: TosAndCpAcceptanceRequest,\n tokenData?: TokenData,\n subscription?: boolean,\n skipEmailValidation?: boolean\n ): Promise<IdentityResponse> {\n this.rsa = new CryptoRSA()\n const privateKey = this.rsa.private()\n\n const symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n const recoveryPassword = symmetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n\n const emailConfirmed = !!skipEmailValidation\n\n const signupRequest: IdentityCreateRequest = {\n practiceUuid: practice.uuid,\n email: email.toLowerCase(),\n emailConfirmed,\n password: hashedPassword,\n publicKey: this.toolbox.encodeToBase64(this.rsa.public()),\n recoveryPassword,\n tosAndCpAcceptance,\n tokenData,\n subscription,\n }\n\n const identity = await this.guardClient.identityCreate(signupRequest)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(identity.id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n return identity\n }\n\n /**\n * Parse the given accessToken claims by calling guard whoami and update theidentity to set it's emailConfirmed flag\n * @param accessToken\n * @returns The identity related to confirmedEmail\n */\n public async confirmEmail(accessToken: string): Promise<IdentityResponse> {\n this.guardClient.setTokens({ accessToken })\n const claims = await this.guardClient.whoAmI()\n return this.guardClient.identityUpdate(claims.sub, {\n emailConfirmed: true,\n })\n }\n\n /**\n * Calls Guard to sign in with the email address, password and one time password (if MFA is enabled)\n * Then recover's the rsa private key from the recovery payload\n *\n * @param practiceUuid\n * @param email\n * @param password\n * @param otp\n * @returns the user identity\n */\n public async signIn(practiceUuid: Uuid, email: string, password: string, otp?: string): Promise<IdentityResponse> {\n const hashedPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(password))\n const tokenRequest: AuthTokenRequest = {\n practiceUuid,\n email: email.toLowerCase(),\n password: hashedPassword,\n otp,\n }\n\n await this.guardClient.authToken(tokenRequest)\n const userUuid = (await this.guardClient.whoAmI()).sub\n\n // Updates the rsa key to the one generated on the backend\n await this.recoverPrivateKeyFromPassword(userUuid, password)\n return await this.guardClient.identityGet(userUuid)\n }\n\n /**\n * Will attempt to recover an existing login session and set back\n * the private key in scope\n */\n public async resumeSession() {\n const id = (await this.guardClient.whoAmI()).sub\n const recoveryPayload = sessionStorage.getItem(sessionStorePrivateKeyName(id))\n const recoveryKey = (await this.guardClient.identityGet(id)).recoveryLogin\n\n if (!recoveryKey || !recoveryPayload) throw IncompleteAuthentication\n\n const symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(recoveryKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * This function let's you encrypt locally an Object\n * @param value the Object to encrypt\n * @returns a LocalEncryptedData Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localEncryptToJsonPayload(value: any): LocalEncryptedData {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = new this.toolbox.CryptoChaCha()\n\n const encryptedData = chaChaKey.jsonEncryptToBase64Payload(value)\n const encryptedKey = this.toolbox.encodeToBase64(this.rsa.encryptToBytes(chaChaKey.key()))\n\n return { encryptedData, encryptedKey }\n }\n\n /**\n * This function let's you decrypt a LocalEncryptedData object\n * @param value a LocalEncryptedData object\n * @returns a decrypted Object\n * @throws IncompleteAuthentication if rsa is not set\n * @calls authenticationCallback if rsa is not set\n */\n public localDecryptJsonPayload({ encryptedKey, encryptedData }: LocalEncryptedData): any {\n if (!this.rsa) {\n if (this.authenticationCallback) {\n this.authenticationCallback(new IncompleteAuthentication())\n }\n\n throw new IncompleteAuthentication()\n }\n\n const chaChaKey = this.rsa.base64DecryptToBytes(encryptedKey)\n const decryptedData = this.toolbox.CryptoChaCha.fromKey(chaChaKey).base64PayloadDecryptToJson(encryptedData)\n\n return decryptedData\n }\n\n /**\n * Effectively kills your \"session\"\n */\n public async signOut() {\n this.rsa = undefined\n this.secrets = []\n this.guardClient.setTokens({\n accessToken: undefined,\n refreshToken: undefined,\n })\n await this.guardClient.authLogout()\n }\n\n /**\n * @name registerPatient\n * @description The complete flow to register a patient\n *\n * Steps:\n * 1. Create a consult (checks if payment has been done)\n * 2. Creates a lockbox\n * 3. Grants lockbox access to all practice personnel\n * 4. Creates secure identification, medical, onboarding data\n * 5. Generates and stores the rsa key pair and recovery payloads\n *\n * @param patientUuid\n * @param consult\n * @param workflow\n * @param recoveryQA\n * @param indexSearch create search index for the consultation if true\n * @param onProgress callback that is called whenever a new step of patient registration is executed. Note: progress ranges from 0 to 1, and descriptionKey is a description of the progress as a key so the app would use it to translate the description\n * @returns\n */\n public async registerPatient(\n patientUuid: Uuid,\n consult: ConsultRequest,\n workflow: WorkflowData,\n recoveryQA?: {\n recoverySecurityQuestions: string[]\n recoverySecurityAnswers: string[]\n },\n indexSearch: boolean = true,\n onProgress?: (progress: number, descriptionKey: string) => void\n ): Promise<RegisterPatientOutput> {\n if (!this.rsa) throw IncompleteAuthentication\n return registerPatient(\n patientUuid,\n consult,\n workflow,\n this,\n this.toolbox.uuid(),\n recoveryQA,\n indexSearch,\n onProgress\n )\n }\n\n /**\n * Creates and stores all relevant refill data\n * - New consultation is created\n * - Stores refill workflow data in the lockbox\n * - Updates the consult to new\n *\n * @param consult\n * @param populatedRefillWorkflow\n * @returns\n */\n public async createRefill(consult: ConsultRequest, populatedRefillWorkflow: WorkflowData): Promise<void> {\n if (!this.rsa) throw IncompleteAuthentication\n return createRefill(consult, populatedRefillWorkflow, this)\n }\n\n /**\n * Fetches all grants, and consultations that exist in each lockbox\n * Then updates the index for the current user with the lockbox consult relationship\n */\n public async forceUpdateIndexEntries() {\n let grants = await this.getGrants()\n\n let indexConsultLockbox: IndexConsultLockbox[] = await Promise.all(\n grants.map(\n async (grant: Grant) =>\n await this.vaultClient\n .lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n [],\n { category: MetadataCategory.Consultation },\n grant.lockboxOwnerUuid\n )\n .then((consults) => {\n try {\n return consults[0].map((consult: any) => {\n return {\n ...consult,\n grant: {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid,\n },\n }\n })\n } catch (e) {\n // No consultations in lockbox or index could not be created\n return []\n }\n })\n .catch(() => [])\n )\n ).then((consults) => consults.flat())\n this.vaultIndexAdd({\n [IndexKey.Consultation]: indexConsultLockbox,\n })\n .then(() => alert('The Index was successfully updated!'))\n .catch(() => console.error('The index failed to update!'))\n }\n\n /**\n * Generates, encrypts and adds entries to vault index for a given index owner\n *\n * @param entries\n * @param indexOwnerUuid\n */\n public async vaultIndexAdd(entries: VaultIndex, indexOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let rsaPub: Uint8Array\n if (indexOwnerUuid) {\n let base64IndexOwnerPubKey = (await this.guardClient.identityGet(indexOwnerUuid)).publicKey\n rsaPub = this.toolbox.decodeFromBase64(base64IndexOwnerPubKey)\n } else {\n rsaPub = this.rsa.public()\n }\n\n let encryptedIndex: EncryptedVaultIndex = {}\n\n for (let keyString of Object.keys(entries)) {\n let key = keyString as keyof VaultIndex\n switch (key) {\n case IndexKey.ConsultationLockbox:\n encryptedIndex[key] = (entries[key] as IndexConsultLockbox[])\n .map((e) => ({\n ...e,\n uniqueHash: e.consultationId,\n }))\n .map(\n (e: IndexConsultLockbox) =>\n ({\n uuid: e.uuid,\n timestamp: e.timestamp,\n uniqueHash: e.uniqueHash,\n encryptedIndexEntry: CryptoRSA.jsonWithPubEncryptToBase64(\n {\n consultationId: e.consultationId,\n grant: e.grant,\n },\n rsaPub\n ),\n } as EncryptedIndexEntry)\n )\n break\n }\n }\n await this.vaultClient.vaultIndexPut(encryptedIndex, indexOwnerUuid)\n }\n\n /**\n * @name grantLockbox\n * @description Grants a lockbox by retrieving the shared secret of the lockbox and encrypting it with the grantees public key\n * @param granteeUuid\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n */\n public async grantLockbox(granteeUuid: Uuid, lockboxUuid: Uuid, lockboxOwnerUuid?: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let secret = (await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)).key()\n let base64GranteePublicKey = (await this.guardClient.identityGet(granteeUuid)).publicKey\n let granteePublicKey = this.toolbox.decodeFromBase64(base64GranteePublicKey)\n\n let granteeEncryptedSecret = CryptoRSA.bytesWithPubEncryptToBase64(secret, granteePublicKey)\n let request: LockboxGrantRequest = {\n encryptedSecret: granteeEncryptedSecret,\n granteeUuid: granteeUuid,\n }\n await this.vaultClient.lockboxGrant(lockboxUuid, request, lockboxOwnerUuid)\n }\n\n /**\n * @name createMessageData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a message string\n * @param lockboxUuid\n * @param message\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageData(\n lockboxUuid: Uuid,\n message: string,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(message)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: 'text/plain',\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createMessageAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @returns the data uuid\n */\n public async createMessageAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(new Uint8Array(await data.arrayBuffer()))\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload({\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n lastModified: data.lastModified,\n size: data.size,\n })\n\n let meta = {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Message,\n contentType: data.type,\n }\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name createAttachmentData\n * @description Creates a Base64 encrypted Payload to send and store in the vault from a file\n * @param lockboxUuid\n * @param data the file stored\n * @param consultationId the consultation for which this message is sent\n * @param category the category for the attachment data\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing file, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createConsultationAttachmentData(\n lockboxUuid: Uuid,\n data: File,\n consultationId: string,\n documentType: DocumentType,\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n return this.createBytesData<Meta | any>(\n lockboxUuid,\n new Uint8Array(await data.arrayBuffer()),\n {\n consultationId,\n category: MetadataCategory.Consultation,\n documentType,\n contentType: data.type,\n },\n {\n author: (await this.guardClient.whoAmI()).sub,\n fileName: data.name,\n },\n lockboxOwnerUuid,\n previousDataUuid,\n withNotification\n )\n }\n\n /**\n * @name createJsonData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a JSON\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createJsonData<T extends Metadata>(\n lockboxUuid: Uuid,\n data: any,\n meta?: T,\n privateMeta?: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.jsonEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n if (withNotification)\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * Get or upsert a data in lockbox\n * @param lockboxUuid the lockbox uuid\n * @param data the data to insert\n * @param publicMetadata the public Metadata\n * @param privateMetadata the private Metadata\n * @param forceReplace set true when the insertion of data requires to replace the data when it exists already\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async getOrInsertJsonData<M extends Metadata>(\n lockboxUuid: Uuid,\n data: any,\n publicMetadata: M,\n privateMetadata: Metadata,\n forceReplace: boolean = false,\n withNotification: boolean = false\n ): Promise<Uuid> {\n let manifest = await this.vaultClient.lockboxManifestGet(lockboxUuid, publicMetadata)\n if (!forceReplace && manifest.length > 0) {\n console.log(`The data for ${JSON.stringify(publicMetadata)} already exist`)\n return manifest[0].dataUuid\n } else\n return (\n await this.createJsonData<M>(\n lockboxUuid,\n data,\n publicMetadata,\n privateMetadata,\n undefined,\n forceReplace && manifest.length > 0 ? manifest[0].dataUuid : undefined, // if forceReplace and data already exist, then replace data. Otherwise insert it\n withNotification\n ).catch((err) => {\n console.error(`Error while upserting data ${JSON.stringify(publicMetadata)} data`, err)\n throw err\n })\n ).dataUuid\n }\n\n /**\n * @name createBytesData\n * @description Creates a Base64 encrypted Payload to send and store in the vault. With the data input as a Bytes\n * @param lockboxUuid\n * @param data\n * @param meta\n * @param privateMeta the metadata that will be secured in the vault\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @param previousDataUuid if it's a revision of existing data, specify the previous data uuid\n * @param withNotification if the insertion of data requires notification\n * @returns the data uuid\n */\n public async createBytesData<T extends Metadata>(\n lockboxUuid: Uuid,\n data: Uint8Array,\n meta: T,\n privateMeta: { [val: string]: any },\n lockboxOwnerUuid?: Uuid,\n previousDataUuid?: Uuid,\n withNotification: boolean = false\n ): Promise<DataCreateResponse> {\n if (!this.rsa) throw IncompleteAuthentication\n let symmetricEncryptor = await this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid)\n let encryptedData = symmetricEncryptor.bytesEncryptToBase64Payload(data)\n let encryptedPrivateMeta = symmetricEncryptor.jsonEncryptToBase64Payload(privateMeta)\n\n let request: LockboxDataRequest = {\n data: encryptedData,\n publicMetadata: meta,\n privateMetadata: encryptedPrivateMeta,\n }\n if (withNotification)\n return this.tellerClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n else return this.vaultClient.lockboxDataStore(lockboxUuid, request, lockboxOwnerUuid, previousDataUuid)\n }\n\n /**\n * @name getJsonData\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * Decrypts the data to a valid JSON object. If this is impossible, the call to the WASM binary will fail\n *\n * @type T is the generic type specifying the return type object of the function\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the data specified by the generic type <T>\n */\n public async getJsonData<T = any>(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<T> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToJson(encryptedPayload.data)\n }\n /**\n * @description Fetches and decrypts the lockbox data with the cached shared secret.\n * @param lockboxUuid\n * @param dataUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns the bytes data\n */\n public async getBytesData(lockboxUuid: Uuid, dataUuid: Uuid, lockboxOwnerUuid?: Uuid): Promise<Uint8Array> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let [encryptedPayload, symmetricDecryptor] = await Promise.all([\n this.vaultClient.lockboxDataGet(lockboxUuid, dataUuid, lockboxOwnerUuid),\n this.getCachedSecretCryptor(lockboxUuid, lockboxOwnerUuid),\n ])\n\n return symmetricDecryptor.base64PayloadDecryptToBytes(encryptedPayload.data)\n }\n\n /**\n * @name getGrants\n * @description Get all lockboxes granted to user with the applied filter\n * @note this function returns cached grants and will not update unless the page is refreshed\n * @todo some versions of lockboxes do not make use of lockbox metadata\n * in this case, all lockboxes need to be filtered one-by-one to find the correct one\n * Remove if this is no longer the case\n * @param filter: the consultationId in which the grant exists\n * @returns decrypted lockboxes granted to user\n */\n public async getGrants(filter?: { consultationId: Uuid }): Promise<Grant[]> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let filterString = JSON.stringify(filter)\n // retrieves cached grants\n if (this.cachedMetadataGrants[filterString]) return this.cachedMetadataGrants[filterString]\n\n // We're using the account role to determine the way a grant is accessed\n let currentAccountRole = await this.getAccountRole()\n if (currentAccountRole.length === 1 && currentAccountRole[0] === OtherRoleType.User) return []\n\n if (\n [OtherRoleType.Patient, OtherRoleType.User].every((requiredRole) =>\n currentAccountRole.includes(requiredRole)\n )\n ) {\n let encryptedGrants\n // if there are no grants with the applied filter from index, attempt for naive filter with backwards compatibility\n if (filter) {\n encryptedGrants = await filterGrantsWithLockboxMetadata(this, filter)\n } else {\n encryptedGrants = (await this.vaultClient.grantsGet()).grants\n }\n const decryptedGrants = await decryptGrants(encryptedGrants, this.rsa)\n // sets the cached grant\n this.cachedMetadataGrants[filterString] = decryptedGrants\n console.info('[sdk:grant] Found grant for patient')\n return decryptedGrants\n }\n // if not a patient, then a practitioner is trying to retrieve a grant, it **Must** contain a filter, otherwise too many grants are possible\n if (!filter) throw MissingGrantFilter\n // Note: will work only if the filter being applied is exclusively a consult id\n const grantsByConsultLockbox = await this.vaultClient\n .vaultIndexGet([IndexKey.ConsultationLockbox], [filter.consultationId])\n .then((res) => res[IndexKey.ConsultationLockbox])\n .catch((e) => {\n console.error(e)\n return []\n })\n\n const decryptedConsults = decryptConsultLockboxGrants(grantsByConsultLockbox ?? [], this.rsa)\n if (decryptedConsults.length > 0) {\n console.info('[sdk:index] Grants found in user`s constant time secure index')\n this.cachedMetadataGrants[filterString] = decryptedConsults\n return this.cachedMetadataGrants[filterString]\n }\n\n // if we have no valid grants, then return nothing\n return []\n }\n\n /**\n * Fetches the role of the account that is logged in\n *\n * @returns the role based scopes defined by the whoami\n */\n async getAccountRole(): Promise<RoleBasedScopes[]> {\n return (await this.guardClient.whoAmI()).scope.split(' ') as RoleBasedScopes[]\n }\n\n /**\n * @name getCachedSecretCryptor\n * @description Retrieves the cached lockbox secret or fetches the secret from vault, then creates the symmetric cryptor and stores it in memory\n * @param lockboxUuid\n * @param lockboxOwnerUuid the lockbox owner (ignored if lockbox is owned by self)\n * @returns\n */\n async getCachedSecretCryptor(lockboxUuid: string, lockboxOwnerUuid?: string): Promise<OroToolbox.CryptoChaCha> {\n if (!this.rsa) throw IncompleteAuthentication\n\n let index = this.secrets.findIndex((secret) => secret.lockboxUuid === lockboxUuid)\n if (index === -1) {\n let encryptedSecret = (await this.vaultClient.lockboxSecretGet(lockboxUuid, lockboxOwnerUuid)).sharedSecret\n\n let secret = this.rsa.base64DecryptToBytes(encryptedSecret)\n let cryptor = this.toolbox.CryptoChaCha.fromKey(secret)\n this.secrets.push({ lockboxUuid, cryptor })\n return cryptor\n } else {\n return this.secrets[index].cryptor\n }\n }\n\n /**\n * Retrieves the patient personal information associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several personal informations data\n * @param consultationId The consultation Id\n * @param category The personal MetadataCategory to fetch\n * @param forceRefresh force data refresh (default to false)\n * @returns the personal data\n */\n public async getPersonalInformationsFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory.Personal | MetadataCategory.ChildPersonal | MetadataCategory.OtherPersonal,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, category, forceRefresh)\n }\n\n /**\n * Retrieves the patient medical data associated to the `consultationId`\n * The `consultationId` only helps to retrieve the patient lockboxes\n * Note: it is possible to have several medical data\n * @param consultationId The consultation Id\n * @param forceRefresh force data refresh (default to false)\n * @returns the medical data\n */\n public async getMedicalDataFromConsultId(\n consultationId: Uuid,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n return this.getMetaCategoryFromConsultId(consultationId, MetadataCategory.Medical, forceRefresh)\n }\n\n private async getMetaCategoryFromConsultId(\n consultationId: Uuid,\n category: MetadataCategory,\n forceRefresh = false\n ): Promise<LocalizedData<PopulatedWorkflowData>[]> {\n let grants = await this.getGrants({ consultationId })\n let workflowData: LocalizedData<PopulatedWorkflowData>[] = []\n for (let grant of grants) {\n let manifest = await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationIds: [consultationId],\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n\n // TODO: find another solution for backwards compatibility (those without the metadata consultationIds)\n if (manifest.length === 0) {\n manifest = (\n await this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category,\n documentType: DocumentType.PopulatedWorkflowData,\n // backward compatiblility with TonTest\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n )\n ).filter((entry) => !entry.metadata.consultationIds) // Keep only entries without associated consultationIds\n }\n let data = await Promise.all(\n manifest.map(async (entry) => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n dataUuid: entry.dataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(grant.lockboxUuid!, entry.dataUuid),\n }\n })\n )\n workflowData = { ...workflowData, ...data }\n }\n return workflowData\n }\n\n /**\n * @description retrieves the personal information stored in the first owned lockbox\n * @param userId The user Id\n * @returns the personal data\n */\n public async getPersonalInformations(userId: Uuid): Promise<LocalizedData<PopulatedWorkflowData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === userId)\n\n if (!grant) {\n throw MissingGrant\n }\n\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n false,\n userId\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<PopulatedWorkflowData>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * Retrieves the grant associated to a consultationId\n * @note returns the first grant only\n * @param consultationId The consultationId\n * @returns the grant\n */\n public async getGrantFromConsultId(consultationId: Uuid): Promise<Grant | undefined> {\n let grants = await this.getGrants({ consultationId })\n\n if (grants.length === 0) {\n throw AssociatedLockboxNotFound\n }\n\n return grants[0]\n }\n\n /**\n * retrieves the identity associated to the `consultationId`\n * @param consultationId The consultation Id\n * @returns the identity\n */\n public async getIdentityFromConsultId(consultationId: Uuid): Promise<IdentityResponse | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (grant && grant.lockboxOwnerUuid) {\n return await this.guardClient.identityGet(grant.lockboxOwnerUuid)\n } else {\n return undefined\n }\n }\n\n /**\n * retrieves the lockbox manifest for a given lockbox and add's its private metadata\n * @note the lockbox manifest will retrieved the cached manifest first unless force refresh is enabled\n * @param lockboxUuid\n * @param filter\n * @param expandPrivateMetadata\n * @param lockboxOwnerUuid\n * @param forceRefresh\n * @returns the lockbox manifest\n */\n public async getLockboxManifest(\n lockboxUuid: Uuid,\n filter: Metadata,\n expandPrivateMetadata: boolean,\n lockboxOwnerUuid?: Uuid,\n forceRefresh: boolean = false\n ): Promise<LockboxManifest> {\n let manifestKey = JSON.stringify({\n lockboxUuid,\n filter,\n expandPrivateMetadata,\n lockboxOwnerUuid,\n })\n if (!forceRefresh && this.cachedManifest[manifestKey]) return this.cachedManifest[manifestKey]\n\n return this.vaultClient.lockboxManifestGet(lockboxUuid, filter, lockboxOwnerUuid).then((manifest) => {\n return Promise.all(\n manifest.map(async (entry) => {\n if (expandPrivateMetadata && entry.metadata.privateMetadata) {\n let privateMeta = await this.getJsonData<Metadata>(\n lockboxUuid!,\n entry.metadata.privateMetadata,\n lockboxOwnerUuid\n )\n entry.metadata = {\n ...entry.metadata,\n ...privateMeta,\n }\n }\n return entry\n })\n ).then((manifest) => (this.cachedManifest[manifestKey] = manifest))\n })\n }\n\n /**\n * @description Create or update the personal information and store it in the first owned lockbox\n * @param identity The identity to use\n * @param data The personal data to store\n * @param dataUuid (optional) The dataUuid to update\n * @returns\n */\n public async createPersonalInformations(\n identity: IdentityResponse,\n data: PopulatedWorkflowData,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PersonalMeta>(\n lockboxUuid,\n data,\n {\n category: MetadataCategory.Personal,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * Create or update user Preference\n * @param identity\n * @param preference\n * @param dataUuid\n * @returns\n */\n public async createUserPreference(\n identity: IdentityResponse,\n preference: UserPreference,\n dataUuid?: string\n ): Promise<DataCreateResponse> {\n const lockboxUuid = (await this.getGrants()).find(\n (lockbox) => lockbox.lockboxOwnerUuid === identity.id\n )?.lockboxUuid\n\n if (lockboxUuid) {\n return this.createJsonData<PreferenceMeta>(\n lockboxUuid,\n preference,\n {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n },\n {},\n undefined,\n dataUuid\n )\n } else {\n throw MissingLockbox\n }\n }\n\n /**\n * retrieves the user preference from a grant\n * @param grant The grant\n * @returns the user preference\n */\n public async getDataFromGrant<T = any>(grant: Grant, filter: Metadata): Promise<LocalizedData<T>> {\n const { lockboxUuid, lockboxOwnerUuid } = grant\n\n if (!lockboxUuid) throw MissingLockbox\n if (!lockboxOwnerUuid) throw MissingLockboxOwner\n const identificationDataUuid = (\n await this.getLockboxManifest(\n lockboxUuid,\n\n filter,\n false,\n grant.lockboxOwnerUuid,\n true\n )\n )[0].dataUuid\n\n return {\n lockboxOwnerUuid,\n lockboxUuid,\n dataUuid: identificationDataUuid,\n data: await this.getJsonData<T>(lockboxUuid, identificationDataUuid),\n }\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getUserPreferenceFromConsultId(consultationId: string): Promise<LocalizedData<UserPreference>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getUserPreference(identity: IdentityResponse): Promise<LocalizedData<UserPreference>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<UserPreference>(grant, {\n category: MetadataCategory.Preference,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference from a consultation id\n * @param consultationId The related consultationId\n * @returns the user preference\n */\n public async getRecoveryDataFromConsultId(consultationId: string): Promise<LocalizedData<RecoveryData>> {\n const grant = await this.getGrantFromConsultId(consultationId)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant<RecoveryData>(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * retrieves the user preference stored in the first owned lockbox from identity\n * @param identity The identity to use\n * @returns the user preference\n */\n public async getRecoveryData(identity: IdentityResponse): Promise<LocalizedData<RecoveryData>> {\n const grant = (await this.getGrants()).find((lockbox) => lockbox.lockboxOwnerUuid === identity.id)\n\n if (!grant) throw MissingGrant\n\n return this.getDataFromGrant(grant, {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n })\n }\n\n /**\n * @name getAssignedConsultations\n * @description finds all assigned or owned consultations for the logged user\n * Steps:\n * - Retrieves all granted lockboxes given to the logged user\n * - for each lockbox, find all consultation ids\n * - for each consultation id, retrieve the consult information\n * @param practiceUuid the uuid of the practice to look consult into\n * @returns the list of consults\n */\n public async getAssignedConsultations(practiceUuid: Uuid): Promise<Consult[]> {\n return Promise.all(\n (await this.getGrants()).map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n true,\n undefined\n ).then((manifest) =>\n Promise.all(\n manifest.map(\n async (entry) =>\n await this.consultClient.getConsultByUUID(entry.metadata.consultationId, practiceUuid)\n )\n ).then((promise) => promise.flat())\n )\n )\n ).then((consults) => consults.flat())\n }\n\n /**\n * Gets the past consultations of the patient as well as his relatives if any\n * @param consultationId any consultation uuid from which we will fetch all the other consultations of the same patient as the owner of this consultation id\n * @param practiceUuid\n */\n public async getPastConsultationsFromConsultId(\n consultationId: string,\n practiceUuid: string\n ): Promise<Consult[] | undefined> {\n const grant = await this.getGrantFromConsultId(consultationId)\n if (!grant) return undefined\n\n let consultationsInLockbox: string[] = (\n await this.vaultClient.lockboxMetadataGet(\n grant.lockboxUuid!,\n ['consultationId'],\n ['consultationId'],\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n },\n grant.lockboxOwnerUuid\n )\n )\n .flat()\n .map((metadata: { consultationId: string }) => metadata.consultationId)\n\n if (consultationsInLockbox.length == 0) return []\n\n return await Promise.all(\n consultationsInLockbox.map(async (consultId: string) => {\n return await this.consultClient.getConsultByUUID(consultId, practiceUuid)\n })\n )\n }\n\n /**\n * @name getPatientConsultationData\n * @description retrieves the consultation data\n * @param consultationId\n * @returns\n */\n public async getPatientConsultationData(\n consultationId: Uuid,\n forceRefresh: boolean = false\n ): Promise<PopulatedWorkflowData[]> {\n //TODO: make use of getPatientDocumentsList instead of doing it manually here\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.PopulatedWorkflowData,\n consultationId, //since we want to update the cached manifest (if another consult data exists)\n },\n true,\n grant.lockboxOwnerUuid,\n forceRefresh\n ).then((manifest) =>\n Promise.all(\n manifest.map((e) =>\n this.getJsonData<PopulatedWorkflowData>(\n grant.lockboxUuid!,\n e.dataUuid,\n grant.lockboxOwnerUuid\n )\n )\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /**\n * This function returns the patient prescriptions\n * @param consultationId\n * @returns\n */\n public async getPatientPrescriptionsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Prescription,\n },\n true,\n consultationId\n )\n }\n\n /**\n * This function returns the patient results\n * @param consultationId\n * @returns\n */\n public async getPatientResultsList(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.Result,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns the patient treatment plan options\n * @param consultationId\n * @returns Document[] corresponding to the patient treatment plan options\n */\n public async getPatientTreatmentPlans(consultationId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n },\n true,\n consultationId\n )\n }\n\n /**\n * returns a specific patient treatment plan option\n * @param consultationId\n * @param treatmentPlanId\n * @returns\n */\n public async getPatientTreatmentPlanByUuid(consultationId: Uuid, treatmentPlanId: Uuid): Promise<Document[]> {\n return this.getPatientDocumentsList(\n {\n category: MetadataCategory.Consultation,\n documentType: DocumentType.TreatmentPlan,\n treatmentPlanId,\n },\n true,\n consultationId\n )\n }\n\n /**\n * @name getPatientDocumentsList\n * @description applies the provided filter to the vault to only find those documents\n * @param filters the applied filters (e.g. type of documents)\n * @param expandPrivateMetadata whether or not, the private metadata needs to be retrieved\n * (more computationally expensive)\n * @param consultationId\n * @returns the filtered document list\n */\n public async getPatientDocumentsList(\n filters: Object,\n expandPrivateMetadata: boolean,\n consultationId: Uuid\n ): Promise<Document[]> {\n return Promise.all(\n (await this.getGrants({ consultationId }))\n .map((grant) =>\n this.getLockboxManifest(\n grant.lockboxUuid!,\n { ...filters, consultationId },\n expandPrivateMetadata,\n grant.lockboxOwnerUuid,\n true\n ).then((manifest) =>\n Promise.all(\n manifest.map(async (entry): Promise<Document> => {\n return {\n lockboxOwnerUuid: grant.lockboxOwnerUuid,\n lockboxUuid: grant.lockboxUuid!,\n ...entry,\n }\n })\n )\n )\n )\n .flat()\n ).then((data) => data.flat())\n }\n\n /****************************************************************************************************************\n * RECOVERY *\n ****************************************************************************************************************/\n\n /**\n * @name recoverPrivateKeyFromSecurityQuestions\n * @description Recovers and sets the rsa private key from the answered security questions\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to recover the key\n */\n public async recoverPrivateKeyFromSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n let shards: SecretShard[] = (await this.guardClient.identityGet(id)).recoverySecurityQuestions!\n let answeredShards = shards\n .filter((shard: any) => {\n // filters all answered security questions\n let indexOfQuestion = recoverySecurityQuestions.indexOf(shard.securityQuestion)\n if (indexOfQuestion === -1) return false\n return recoverySecurityAnswers[indexOfQuestion] && recoverySecurityAnswers[indexOfQuestion] != ''\n })\n .map((item: any) => {\n // appends the security answer to the answered shards\n let index = recoverySecurityQuestions.indexOf(item.securityQuestion)\n item.securityAnswer = recoverySecurityAnswers[index]\n return item\n })\n try {\n // reconstructs the key from the answered security answers\n let privateKey = this.toolbox.reconstructSecret(answeredShards, threshold)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n } catch (e) {\n console.error(e)\n }\n }\n\n /**\n * @name recoverPrivateKeyFromPassword\n * @description Recovers and sets the rsa private key from the password\n * @param id\n * @param password\n */\n public async recoverPrivateKeyFromPassword(id: Uuid, password: string) {\n let identity = await this.guardClient.identityGet(id)\n\n let recoveryPayload = identity.recoveryPassword\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(password)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n\n if (identity.recoveryLogin) {\n //Ensure we can recover from a page reload\n let symetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(identity.recoveryLogin)\n sessionStorage.setItem(\n sessionStorePrivateKeyName(id),\n symetricEncryptor.bytesEncryptToBase64Payload(privateKey)\n )\n }\n\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @name recoverPrivateKeyFromMasterKey\n * @description Recovers and sets the rsa private key from the master key\n * @param id\n * @param masterKey\n */\n public async recoverPrivateKeyFromMasterKey(id: Uuid, masterKey: string) {\n let recoveryPayload = (await this.guardClient.identityGet(id)).recoveryMasterKey!\n let symmetricDecryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let privateKey = symmetricDecryptor.base64PayloadDecryptToBytes(recoveryPayload)\n this.rsa = this.toolbox.CryptoRSA.fromKey(privateKey)\n }\n\n /**\n * @description Generates and updates the security questions and answers payload using new recovery questions and answers\n * Important: Since the security questions generate a payload for the private key, they will never be stored on the device as they must remain secret!!!\n * @param id\n * @param recoverySecurityQuestions\n * @param recoverySecurityAnswers\n * @param threshold the number of answers needed to rebuild the secret\n */\n public async updateSecurityQuestions(\n id: Uuid,\n recoverySecurityQuestions: string[],\n recoverySecurityAnswers: string[],\n threshold: number\n ) {\n if (!this.rsa) throw IncompleteAuthentication\n let securityQuestionPayload = this.toolbox.breakSecretIntoShards(\n recoverySecurityQuestions,\n recoverySecurityAnswers,\n this.rsa.private(),\n threshold\n )\n let updateRequest = {\n recoverySecurityQuestions: securityQuestionPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the payload encrypted payload and updates the password itself (double hash)\n * @important\n * the recovery payload uses a singly hashed password and the password stored is doubly hashed so\n * the stored password cannot derive the decryption key in the payload\n * @note\n * the old password must be provided when not performing an account recovery\n * @param id\n * @param newPassword\n * @param oldPassword\n */\n public async updatePassword(id: Uuid, newPassword: string, oldPassword?: string) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(newPassword)\n let passwordPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n if (oldPassword) {\n oldPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(oldPassword))\n }\n\n newPassword = this.toolbox.hashStringToBase64(this.toolbox.hashStringToBase64(newPassword))\n\n let updateRequest = {\n password: {\n oldPassword,\n newPassword,\n },\n recoveryPassword: passwordPayload,\n }\n\n return await this.guardClient.identityUpdate(id, updateRequest)\n }\n\n /**\n * @description Generates and stores the master key encrypted payload\n * Important\n * Since the master key is used to generate a payload for the private key, it will never be stored on the device as it must remain secret!\n * @param id\n * @param masterKey\n * @param lockboxUuid\n */\n async updateMasterKey(id: Uuid, masterKey: string, lockboxUuid: Uuid) {\n if (!this.rsa) throw IncompleteAuthentication\n\n let symmetricEncryptor = this.toolbox.CryptoChaCha.fromPassphrase(masterKey)\n let masterKeyPayload = symmetricEncryptor.bytesEncryptToBase64Payload(this.rsa.private())\n let updateRequest = { recoveryMasterKey: masterKeyPayload }\n const updatedIdentity = await this.guardClient.identityUpdate(id, updateRequest)\n\n await this.getOrInsertJsonData<RecoveryMeta>(\n lockboxUuid,\n { masterKey },\n {\n category: MetadataCategory.Recovery,\n contentType: 'application/json',\n },\n {},\n true\n )\n\n return updatedIdentity\n }\n}\n","import { AxiosService, CliniaResponse, FacetFilter, PlaceData } from \"oro-sdk-apis\"\n\nexport class CliniaService {\n private api: AxiosService\n\n constructor(private url: string, apiKey: string, private locale?: string) {\n this.api = new AxiosService({ headers: { 'X-Clinia-API-Key': apiKey } })\n }\n\n public placeSearch(searchOptions: {\n locale?: string\n query?: string\n facetFilters?: FacetFilter[]\n location?: string\n aroundLatLng?: string\n page?: number\n }) {\n const { locale, ...data } = searchOptions\n\n return this.api.post<CliniaResponse<PlaceData>>(\n `${this.url}/search/v1/indexes/health_facility/query`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n }\n\n public placeMatch(\n searchOptions: {\n locale?: string\n name?: string\n address?: string\n postalCode?: string\n place?: string\n region?: string\n country?: string\n },\n type?: string\n ) {\n const { locale, ...data } = searchOptions\n\n let request = this.api.post<PlaceData[]>(\n `${this.url}/search/v1/matches`,\n data,\n {\n params: { locale: locale ?? this.locale },\n }\n )\n\n if (type) {\n request = request.then((places) =>\n places.filter((place) => place.type === type)\n )\n }\n\n return request\n }\n}\n","import initApis from 'oro-sdk-apis'\nimport { OroClient } from './client'\nimport * as OroToolboxNamespace from 'oro-toolbox'\n\nexport type OroToolbox = typeof OroToolboxNamespace\n\nexport let wasmPath = 'node_modules/oro-toolbox'\n\n/**\n * This function helps you to initialize and OroClient instance\n * @param toolbox the OroToolbox object\n * @param tellerBaseURL the teller service base URL \n * @param vaultBaseURL the vault service base URL \n * @param guardBaseURL the guard service base URL \n * @param searchbaseURL the search service base URL\n * @param practiceBaseURL the practice service base URL \n * @param consultBaseURL the consult service base URL \n * @param workflowBaseURL the workflow service base URL \n * @param diagnosisBaseURL the diagnosis service base URL \n * @param authenticationCallback (optional) authenticationCallback the authentification callback \n * @returns an instance of OroClient\n */\nconst init = (\n toolbox: OroToolbox,\n tellerBaseURL: string,\n vaultBaseURL: string,\n guardBaseURL: string,\n searchBaseURL: string,\n practiceBaseURL: string,\n consultBaseURL: string,\n workflowBaseURL: string,\n diagnosisBaseURL: string,\n authenticationCallback?: (err: Error) => void\n) => {\n const {\n tellerService,\n practiceService,\n consultService,\n vaultService,\n guardService,\n searchService,\n workflowService,\n diagnosisService,\n } = initApis(\n {\n tellerBaseURL,\n vaultBaseURL,\n guardBaseURL,\n searchBaseURL,\n practiceBaseURL,\n consultBaseURL,\n workflowBaseURL,\n diagnosisBaseURL,\n },\n authenticationCallback\n )\n\n const client = new OroClient(\n toolbox,\n tellerService!,\n vaultService!,\n guardService!,\n searchService!,\n practiceService!,\n consultService!,\n workflowService!,\n diagnosisService!,\n authenticationCallback\n )\n\n return client\n}\n\nexport { OroClient } from './client'\nexport * from 'oro-sdk-apis'\nexport * from './models'\nexport * from './helpers'\nexport * from './services'\nexport { OroToolboxNamespace }\nexport default init\n"],"names":["personalMetaToPrefix","MetadataCategory","Personal","ChildPersonal","OtherPersonal","identificationToPersonalInformations","data","category","prefix","birthday","firstname","gender","name","phone","zip","hid","pharmacy","address","toActualObject","ret","Object","entries","fields","forEach","field","displayedAnswer","answer","sessionStorePrivateKeyName","id","IncompleteAuthentication","_inheritsLoose","Error","MissingGrant","MissingGrantFilter","MissingLockbox","MissingLockboxOwner","AssociatedLockboxNotFound","WorkflowAnswersMissingError","filterTriggeredAnsweredWithKind","workflowData","kind","selectedAnswers","_context","flattenedAnswers","flattenSelectedAnswers","triggeredQuestionsWithKind","fromEntries","pages","map","a","questions","filter","question","isTriggered","triggers","flat","samePageAnswers","reduce","prev","cur","res","keys","questionFieldName","getWorkflowDataByCategory","_context2","triggeredQuestions","Promise","all","e","k","populateWorkflowField","then","populatedValue","workflowCreatedAt","createdAt","workflowId","locale","err","console","error","getImagesFromIndexDb","_context3","getMany","v","answerValue","undefined","_context4","answers","text","value","images","image","imageData","resolve","includes","Array","isArray","some","subSetTriggers","every","trigger","linearAnswers","push","values","getInitialisedSelectedAnswers","workflow","useDefault","page","defaultValue","getOrCreatePatientConsultationUuid","consult","oroClient","practiceClient","practiceGetPayment","uuidPractice","idStripeInvoiceOrPaymentIntent","payment","uuidConsult","consultClient","getConsultByUUID","consultCreate","registerPatient","patientUuid","consultRequest","masterKey","recoveryQA","indexSearch","onProgress","lockboxUuid","practitionerAdmin","retry","identity","errorsThrown","stepsTotalNum","currentStep","setTimeout","practiceGetFromUuid","uuidAdmin","practiceGetPractitioners","log","practitioners","getOrCreatePatientLockbox","guardClient","identityGet","grantLockbox","grantPromises","practitioner","uuid","IndexKey","ConsultationLockbox","grant","lockboxOwnerUuid","consultationId","consultIndex","consultIndexPromises","vaultIndexAdd","storeImageAliases","storePatientData","isoLanguageRequired","_identity","recoveryMasterKey","updateMasterKey","_identity2","recoverySecurityQuestions","updateSecurityQuestions","recoverySecurityAnswers","buildConsultSearchIndex","length","updateConsultByUUID","statusMedical","MedicalStatus","New","cleanIndex","_context5","getGrants","grants","vaultClient","lockboxCreate","lockboxResponse","authRefresh","tokens","setTokens","accessToken","refreshToken","whoAmI","isoLanguage","getOrInsertJsonData","Raw","contentType","Consultation","documentType","DocumentType","PopulatedWorkflowData","Medical","consultationIds","extractAndStorePersonalWorkflowData","Preference","dataUuids","progress","_context7","nonNullImages","img","storedImagesNum","totalImagesNum","promises","ImageAlias","idbId","progressStepValue","Math","round","extractPersonalInfoFromWorkflowData","personalInfoPopulatedWfData","childPersonalInfoPopulatedWfData","otherPersonalInfoPopulatedWfData","terms","shortId","_context10","_yield$extractPersona","personalInfo","childPersonalInfo","otherPersonalInfo","searchClient","index","decryptGrants","encryptedGrants","rsaKey","encryptedLockbox","uuidParse","base64DecryptToBytes","decryptConsultLockboxGrants","encryptedConsultLockboxes","base64DecryptToJson","encryptedIndexEntry","grantsTuple","grantTuples","createRefill","populatedRefillWorkflow","newConsult","Refill","filterGrantsWithLockboxMetadata","filteredGrants","_iterator","lockboxMetadataGet","OroClient","toolbox","tellerClient","workflowClient","diagnosisClient","authenticationCallback","this","_proto","cachedMetadataGrants","cachedManifest","signUp","email","password","practice","tosAndCpAcceptance","tokenData","subscription","skipEmailValidation","rsa","CryptoRSA","privateKey","symmetricEncryptor","CryptoChaCha","fromPassphrase","recoveryPassword","bytesEncryptToBase64Payload","hashedPassword","hashStringToBase64","emailConfirmed","signupRequest","practiceUuid","toLowerCase","publicKey","encodeToBase64","identityCreate","recoveryLogin","symetricEncryptor","sessionStorage","setItem","confirmEmail","identityUpdate","sub","signIn","otp","tokenRequest","authToken","userUuid","recoverPrivateKeyFromPassword","resumeSession","recoveryPayload","getItem","recoveryKey","symmetricDecryptor","base64PayloadDecryptToBytes","fromKey","localEncryptToJsonPayload","chaChaKey","encryptedData","jsonEncryptToBase64Payload","encryptedKey","encryptToBytes","key","localDecryptJsonPayload","base64PayloadDecryptToJson","signOut","secrets","_context6","authLogout","_context8","forceUpdateIndexEntries","_context9","_this","consults","alert","indexOwnerUuid","_context11","rsaPub","decodeFromBase64","encryptedIndex","_i","uniqueHash","timestamp","jsonWithPubEncryptToBase64","vaultIndexPut","granteeUuid","_context12","getCachedSecretCryptor","secret","granteePublicKey","granteeEncryptedSecret","bytesWithPubEncryptToBase64","request","encryptedSecret","lockboxGrant","createMessageData","message","previousDataUuid","_context13","author","encryptedPrivateMeta","lockboxDataStore","publicMetadata","Message","privateMetadata","createMessageAttachmentData","_context14","Uint8Array","arrayBuffer","lastModified","size","fileName","type","createConsultationAttachmentData","withNotification","_context15","createBytesData","createJsonData","meta","privateMeta","_context16","forceReplace","_context17","lockboxManifestGet","manifest","JSON","stringify","dataUuid","_context18","getJsonData","_context19","lockboxDataGet","_yield$Promise$all","getBytesData","_context20","_yield$Promise$all2","_context21","filterString","getAccountRole","currentAccountRole","OtherRoleType","User","Patient","requiredRole","grantsGet","decryptedGrants","info","vaultIndexGet","decryptedConsults","grantsByConsultLockbox","_context22","scope","split","_context23","findIndex","lockboxSecretGet","sharedSecret","cryptor","getPersonalInformationsFromConsultId","forceRefresh","getMetaCategoryFromConsultId","getMedicalDataFromConsultId","_context28","_loop","_context27","_this2","getLockboxManifest","entry","metadata","_context26","getPersonalInformations","userId","_context29","find","lockbox","identificationDataUuid","getGrantFromConsultId","_context30","getIdentityFromConsultId","_context31","expandPrivateMetadata","manifestKey","_context33","_context32","_this3","createPersonalInformations","_context34","_yield$this$getGrants","createUserPreference","preference","_context35","_yield$this$getGrants2","getDataFromGrant","_context36","getUserPreferenceFromConsultId","_context37","getUserPreference","_context38","getRecoveryDataFromConsultId","_context39","Recovery","getRecoveryData","_context40","getAssignedConsultations","_context42","_this4","_context41","promise","getPastConsultationsFromConsultId","_context44","consultationsInLockbox","consultId","_context43","_this5","getPatientConsultationData","_context45","_this6","getPatientPrescriptionsList","getPatientDocumentsList","Prescription","getPatientResultsList","Result","getPatientTreatmentPlans","TreatmentPlan","getPatientTreatmentPlanByUuid","treatmentPlanId","filters","_context51","_this7","recoverPrivateKeyFromSecurityQuestions","threshold","_context52","answeredShards","shard","indexOfQuestion","indexOf","securityQuestion","item","securityAnswer","reconstructSecret","_context53","recoverPrivateKeyFromMasterKey","_context54","_context55","securityQuestionPayload","breakSecretIntoShards","updateRequest","updatePassword","newPassword","oldPassword","_context56","passwordPayload","_context57","masterKeyPayload","updatedIdentity","CliniaService","url","apiKey","api","AxiosService","headers","X-Clinia-API-Key","placeSearch","searchOptions","post","params","placeMatch","places","place","tellerBaseURL","vaultBaseURL","guardBaseURL","searchBaseURL","practiceBaseURL","consultBaseURL","workflowBaseURL","diagnosisBaseURL","initApis","tellerService","vaultService","guardService","searchService","practiceService","consultService","workflowService","diagnosisService","arrSelectedLocality","flatMap","currentAnswerPage","arrCountryFields","workflowFieldName","arrProvinceFields","arrConsultLocalFields","currentFieldName","currentSelectedLocality","startsWith","allowedLocalityPatterns","indexPriority","isoValue","finalLocality","extractedSelected","exec","indexSelectedPriority","isoSelectedValue","extractedFinal","indexFinalPriority","populatedWorkflow","filledWorkflow","parse","pageIdx","isTreatmentWorking","hasSideEffects","deliveryAddress","culDeSacs","hidePlanRules","title","groups","fieldsAndGroups","label","inline","inlineLabel","metaCategory","73bec6eb-0310-4787-af3c-ac9c291737b2","e193951f-986f-4db3-bede-903045a1804a","1b87ad22-d316-4fac-9c7f-8f4ccb841aed","ab7f5a41-c351-4f5d-a568-e38f9f200e9a","youPharmacy","minorLabel","summaryLabel","youAddress","infos"],"mappings":"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"}