@icure/api 8.6.4 → 8.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/icc-api/api/IccFormApi.d.ts +81 -0
- package/icc-api/api/IccFormApi.js +213 -0
- package/icc-api/api/IccFormApi.js.map +1 -1
- package/icc-x-api/icc-accesslog-x-api.d.ts +93 -0
- package/icc-x-api/icc-accesslog-x-api.js +93 -0
- package/icc-x-api/icc-accesslog-x-api.js.map +1 -1
- package/icc-x-api/icc-calendar-item-x-api.d.ts +122 -0
- package/icc-x-api/icc-calendar-item-x-api.js +122 -0
- package/icc-x-api/icc-calendar-item-x-api.js.map +1 -1
- package/icc-x-api/icc-classification-x-api.d.ts +20 -0
- package/icc-x-api/icc-classification-x-api.js +20 -0
- package/icc-x-api/icc-classification-x-api.js.map +1 -1
- package/icc-x-api/icc-code-x-api.d.ts +23 -0
- package/icc-x-api/icc-code-x-api.js +23 -0
- package/icc-x-api/icc-code-x-api.js.map +1 -1
- package/icc-x-api/icc-contact-x-api.d.ts +219 -1
- package/icc-x-api/icc-contact-x-api.js +219 -2
- package/icc-x-api/icc-contact-x-api.js.map +1 -1
- package/icc-x-api/icc-data-owner-x-api.d.ts +14 -3
- package/icc-x-api/icc-data-owner-x-api.js +14 -3
- package/icc-x-api/icc-data-owner-x-api.js.map +1 -1
- package/icc-x-api/icc-device-x-api.d.ts +8 -0
- package/icc-x-api/icc-device-x-api.js +8 -0
- package/icc-x-api/icc-device-x-api.js.map +1 -1
- package/icc-x-api/icc-doctemplate-x-api.d.ts +26 -0
- package/icc-x-api/icc-doctemplate-x-api.js +26 -0
- package/icc-x-api/icc-doctemplate-x-api.js.map +1 -1
- package/icc-x-api/icc-document-x-api.d.ts +114 -1
- package/icc-x-api/icc-document-x-api.js +127 -1
- package/icc-x-api/icc-document-x-api.js.map +1 -1
- package/icc-x-api/icc-form-x-api.d.ts +34 -4
- package/icc-x-api/icc-form-x-api.js +34 -4
- package/icc-x-api/icc-form-x-api.js.map +1 -1
- package/icc-x-api/icc-hcparty-x-api.d.ts +67 -0
- package/icc-x-api/icc-hcparty-x-api.js +67 -0
- package/icc-x-api/icc-hcparty-x-api.js.map +1 -1
- package/icc-x-api/icc-helement-x-api.d.ts +141 -0
- package/icc-x-api/icc-helement-x-api.js +141 -0
- package/icc-x-api/icc-helement-x-api.js.map +1 -1
- package/icc-x-api/icc-invoice-x-api.d.ts +54 -0
- package/icc-x-api/icc-invoice-x-api.js +54 -0
- package/icc-x-api/icc-invoice-x-api.js.map +1 -1
- package/icc-x-api/icc-message-x-api.d.ts +162 -0
- package/icc-x-api/icc-message-x-api.js +162 -0
- package/icc-x-api/icc-message-x-api.js.map +1 -1
- package/icc-x-api/icc-patient-x-api.d.ts +245 -0
- package/icc-x-api/icc-patient-x-api.js +245 -1
- package/icc-x-api/icc-patient-x-api.js.map +1 -1
- package/icc-x-api/icc-receipt-x-api.d.ts +25 -0
- package/icc-x-api/icc-receipt-x-api.js +25 -0
- package/icc-x-api/icc-receipt-x-api.js.map +1 -1
- package/icc-x-api/icc-user-x-api.d.ts +25 -0
- package/icc-x-api/icc-user-x-api.js +25 -0
- package/icc-x-api/icc-user-x-api.js.map +1 -1
- package/package.json +1 -1
- package/test/icc-x-api/icc-form-x-api.js +265 -1
- package/test/icc-x-api/icc-form-x-api.js.map +1 -1
- package/test/utils/roles.js +5 -0
- package/test/utils/roles.js.map +1 -1
- package/test/utils/test_utils.js +1 -21
- package/test/utils/test_utils.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icc-receipt-x-api.js","sourceRoot":"","sources":["../../icc-x-api/icc-receipt-x-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { IccReceiptApi } from '../icc-api'\nimport { IccCryptoXApi } from './icc-crypto-x-api'\nimport * as _ from 'lodash'\nimport * as models from '../icc-api/model/models'\nimport { IccDataOwnerXApi } from './icc-data-owner-x-api'\nimport { AuthenticationProvider, NoAuthenticationProvider } from './auth/AuthenticationProvider'\nimport { ShareMetadataBehaviour } from './crypto/ShareMetadataBehaviour'\nimport { ShareResult } from './utils/ShareResult'\nimport { EntityShareRequest } from '../icc-api/model/requests/EntityShareRequest'\nimport RequestedPermissionEnum = EntityShareRequest.RequestedPermissionEnum\nimport { SecureDelegation } from '../icc-api/model/SecureDelegation'\nimport AccessLevelEnum = SecureDelegation.AccessLevelEnum\nimport { XHR } from '../icc-api/api/XHR'\nimport { EncryptedEntityXApi } from './basexapi/EncryptedEntityXApi'\nimport { MaintenanceTask } from '../icc-api/model/models'\nimport { EntityWithDelegationTypeName, ua2ab } from './utils'\n\nexport class IccReceiptXApi extends IccReceiptApi implements EncryptedEntityXApi<models.Receipt> {\n get headers(): Promise<Array<XHR.Header>> {\n return super.headers.then((h) => this.crypto.accessControlKeysHeaders.addAccessControlKeysHeaders(h, EntityWithDelegationTypeName.Receipt))\n }\n\n constructor(\n host: string,\n headers: { [key: string]: string },\n private readonly crypto: IccCryptoXApi,\n private readonly dataOwnerApi: IccDataOwnerXApi,\n private readonly autofillAuthor: boolean,\n authenticationProvider: AuthenticationProvider = new NoAuthenticationProvider(),\n fetchImpl: (input: RequestInfo, init?: RequestInit) => Promise<Response> = typeof window !== 'undefined'\n ? window.fetch\n : typeof self !== 'undefined'\n ? self.fetch\n : fetch\n ) {\n super(host, headers, authenticationProvider, fetchImpl)\n this.dataOwnerApi = dataOwnerApi\n }\n\n /**\n * Creates a new instance of receipt with initialised encryption metadata (not in the database).\n * @param user the current user.\n * @param r initialised data for the receipt. Metadata such as id, creation data, etc. will be automatically initialised, but you can specify\n * other kinds of data or overwrite generated metadata with this. You can't specify encryption metadata.\n * @param options optional parameters:\n * - additionalDelegates: delegates which will have access to the entity in addition to the current data owner and delegates from the\n * auto-delegations. Must be an object which associates each data owner id with the access level to give to that data owner. May overlap with\n * auto-delegations, in such case the access level specified here will be used.\n * - ignoreAutoDelegations: if true the data won't be shared with the autodelegations of the user, but only with additional delegates\n * - alternateRootDelegation: by default a new entity is created with a root delegation from self to self. In keyless mode this is not possible,\n * and instead the root delegation will be from self to another. You have to specify which delegate will be part of the root delegation.\n * @return a new instance of receipt.\n */\n async newInstance(\n user: models.User,\n r: any,\n options: {\n additionalDelegates?: { [dataOwnerId: string]: AccessLevelEnum }\n ignoreAutoDelegations?: boolean\n alternateRootDelegation?: string\n } = {}\n ): Promise<models.Receipt> {\n const receipt = new models.Receipt({\n ...(r ?? {}),\n _type: 'org.taktik.icure.entities.Receipt',\n id: r?.id ?? this.crypto.primitives.randomUuid(),\n created: r?.created ?? new Date().getTime(),\n modified: r?.modified ?? new Date().getTime(),\n responsible: r?.responsible ?? (this.autofillAuthor ? this.dataOwnerApi.getDataOwnerIdOf(user) : undefined),\n author: r?.author ?? (this.autofillAuthor ? user.id : undefined),\n codes: r?.codes ?? [],\n tags: r?.tags ?? [],\n })\n\n const extraDelegations = {\n ...(options.ignoreAutoDelegations == true\n ? {}\n : Object.fromEntries(\n [...(user.autoDelegations?.all ?? []), ...(user.autoDelegations?.medicalInformation ?? [])].map((d) => [d, AccessLevelEnum.WRITE])\n )),\n ...(options?.additionalDelegates ?? {}),\n }\n return new models.Receipt(\n await this.crypto.xapi\n .entityWithInitialisedEncryptedMetadata(\n receipt,\n EntityWithDelegationTypeName.Receipt,\n undefined,\n undefined,\n true,\n extraDelegations,\n options.alternateRootDelegation\n )\n .then((x) => x.updatedEntity)\n )\n }\n\n logReceipt(user: models.User, docId: string, refs: Array<string>, blobType: string, blob: ArrayBuffer) {\n return this.newInstance(user, { documentId: docId, references: refs })\n .then((rcpt) => this.createReceipt(rcpt))\n .then((rcpt) => (blob.byteLength != 0 ? this.setReceiptAttachmentForBlobType(rcpt.id!, rcpt.rev!, blobType, <any>blob) : Promise.resolve(rcpt)))\n }\n\n /**\n * Adds an attachment to a receipt, encrypting it on client side using the encryption keys of the provided receipt.\n * @param receipt a receipt.\n * @param blobType the type of the attachment.\n * @param attachment a attachment for the receipt.\n * @return the updated receipt.\n */\n async encryptAndSetReceiptAttachment(receipt: models.Receipt, blobType: string, attachment: ArrayBuffer | Uint8Array): Promise<models.Receipt> {\n const { encryptedData, updatedEntity } = await this.crypto.xapi.encryptDataOf(receipt, EntityWithDelegationTypeName.Receipt, attachment, (r) =>\n this.modifyReceipt(r)\n )\n return await this.setReceiptAttachmentForBlobType(receipt.id!, updatedEntity?.rev ?? receipt.rev!, blobType, encryptedData)\n }\n\n /**\n * Adds an unencrypted attachment to a receipt.\n * @param receipt a receipt.\n * @param blobType the type of the attachment.\n * @param attachment a attachment for the receipt.\n * @return the updated receipt.\n */\n async setClearReceiptAttachment(receipt: models.Receipt, blobType: string, attachment: ArrayBuffer | Uint8Array): Promise<models.Receipt> {\n return await this.setReceiptAttachmentForBlobType(receipt.id!, receipt.rev!, blobType, ua2ab(attachment))\n }\n\n /**\n * Gets the attachment of a receipt and tries to decrypt it using the encryption keys of the receipt.\n * @param receipt a receipt.\n * @param attachmentId id of the attachment of this receipt to retrieve.\n * @param validator optionally a validator function which checks if the decryption was successful. In cases where the receipt has many encryption\n * keys and it is unclear which one should be used this function can help to detect bad decryptions.\n * @return the decrypted attachment, if it could be decrypted, else the encrypted attachment.\n */\n async getAndDecryptReceiptAttachment(\n receipt: models.Receipt,\n attachmentId: string,\n validator: (decrypted: ArrayBuffer) => Promise<boolean> = () => Promise.resolve(true)\n ): Promise<ArrayBuffer> {\n const retrieved = await this.getAndTryDecryptReceiptAttachment(receipt, attachmentId, (x) => validator(x))\n if (!retrieved.wasDecrypted) throw new Error(`No valid key found to decrypt data of receipt ${receipt.id}.`)\n return retrieved.data\n }\n\n /**\n * Gets the attachment of a receipt and tries to decrypt it using the encryption keys of the receipt.\n * @param receipt a receipt.\n * @param attachmentId id of the attachment of this receipt to retrieve.\n * @param validator optionally a validator function which checks if the decryption was successful. In cases where the receipt has many encryption\n * keys and it is unclear which one should be used this function can help to detect bad decryptions.\n * @return an object containing:\n * - data: the decrypted attachment, if it could be decrypted, else the encrypted attachment.\n * - wasDecrypted: if the data was successfully decrypted or not\n */\n async getAndTryDecryptReceiptAttachment(\n receipt: models.Receipt,\n attachmentId: string,\n validator: (decrypted: ArrayBuffer) => Promise<boolean> = () => Promise.resolve(true)\n ): Promise<{ data: ArrayBuffer; wasDecrypted: boolean }> {\n return await this.crypto.xapi.tryDecryptDataOf(\n { entity: receipt, type: EntityWithDelegationTypeName.Receipt },\n await this.getReceiptAttachment(receipt.id!, attachmentId),\n (x) => validator(x)\n )\n }\n\n /**\n * @return if the logged data owner has write access to the content of the given receipt\n */\n async hasWriteAccess(receipt: models.Receipt): Promise<boolean> {\n return this.crypto.xapi.hasWriteAccess({ entity: receipt, type: EntityWithDelegationTypeName.Receipt })\n }\n\n /**\n * Share an existing receipt with other data owners, allowing them to access the non-encrypted data of the receipt and optionally also\n * the encrypted content, with read-only or read-write permissions.\n * @param delegateId the id of the data owner which will be granted access to the receipt.\n * @param receipt the receipt to share.\n * @param options optional parameters to customize the sharing behaviour:\n * - shareSecretIds: specifies which secret ids of the entity should be shared. If not provided all secret ids available to the current user will be shared\n * - shareEncryptionKey: specifies if the encryption key of the access log should be shared with the delegate, giving access to all encrypted\n * content of the entity, excluding other encrypted metadata (defaults to {@link ShareMetadataBehaviour.IF_AVAILABLE}). Note that by default a\n * receipt does not have encrypted content.\n * - requestedPermissions: the requested permissions for the delegate, defaults to {@link RequestedPermissionEnum.MAX_WRITE}.\n * @return the updated entity\n */\n async shareWith(\n delegateId: string,\n receipt: models.Receipt,\n options: {\n shareSecretIds?: string[]\n requestedPermissions?: RequestedPermissionEnum\n shareEncryptionKey?: ShareMetadataBehaviour // Defaults to ShareMetadataBehaviour.IF_AVAILABLE\n } = {}\n ): Promise<models.Receipt> {\n return this.shareWithMany(receipt, { [delegateId]: options })\n }\n\n /**\n * Share an existing receipt with other data owners, allowing them to access the non-encrypted data of the receipt and optionally also\n * the encrypted content, with read-only or read-write permissions.\n * @param receipt the receipt to share.\n * @param delegates associates the id of data owners which will be granted access to the entity, to the following sharing options:\n * - shareSecretIds: specifies which secret ids of the entity should be shared. If not provided all secret ids available to the current user will be shared\n * - shareEncryptionKey: specifies if the encryption key of the access log should be shared with the delegate, giving access to all encrypted\n * content of the entity, excluding other encrypted metadata (defaults to {@link ShareMetadataBehaviour.IF_AVAILABLE}). Note that by default a\n * receipt does not have encrypted content.\n * - requestedPermissions: the requested permissions for the delegate, defaults to {@link RequestedPermissionEnum.MAX_WRITE}.\n * @return the updated entity\n */\n async shareWithMany(\n receipt: models.Receipt,\n delegates: {\n [delegateId: string]: {\n shareSecretIds?: string[]\n requestedPermissions?: RequestedPermissionEnum\n shareEncryptionKey?: ShareMetadataBehaviour // Defaults to ShareMetadataBehaviour.IF_AVAILABLE\n }\n }\n ): Promise<models.Receipt> {\n return (await this.tryShareWithMany(receipt, delegates)).updatedEntityOrThrow\n }\n\n /**\n * Share an existing receipt with other data owners, allowing them to access the non-encrypted data of the receipt and optionally also\n * the encrypted content, with read-only or read-write permissions.\n * @param receipt the receipt to share.\n * @param delegates associates the id of data owners which will be granted access to the entity, to the following sharing options:\n * - shareSecretIds: specifies which secret ids of the entity should be shared. If not provided all secret ids available to the current user will be shared\n * - shareEncryptionKey: specifies if the encryption key of the access log should be shared with the delegate, giving access to all encrypted\n * content of the entity, excluding other encrypted metadata (defaults to {@link ShareMetadataBehaviour.IF_AVAILABLE}). Note that by default a\n * receipt does not have encrypted content.\n * - requestedPermissions: the requested permissions for the delegate, defaults to {@link RequestedPermissionEnum.MAX_WRITE}.\n * @return a promise which will contain the result of the operation: the updated entity if the operation was successful or details of the error if\n * the operation failed.\n */\n async tryShareWithMany(\n receipt: models.Receipt,\n delegates: {\n [delegateId: string]: {\n shareSecretIds?: string[]\n requestedPermissions?: RequestedPermissionEnum\n shareEncryptionKey?: ShareMetadataBehaviour // Defaults to ShareMetadataBehaviour.IF_AVAILABLE\n }\n }\n ): Promise<ShareResult<models.Receipt>> {\n // All entities should have an encryption key.\n const entityWithEncryptionKey = await this.crypto.xapi.ensureEncryptionKeysInitialised(receipt, EntityWithDelegationTypeName.Receipt)\n const updatedEntity = entityWithEncryptionKey ? await this.modifyReceipt(entityWithEncryptionKey) : receipt\n return this.crypto.xapi.simpleShareOrUpdateEncryptedEntityMetadata(\n {\n entity: updatedEntity,\n type: EntityWithDelegationTypeName.Receipt,\n },\n Object.fromEntries(\n Object.entries(delegates).map(([delegateId, options]) => [\n delegateId,\n {\n requestedPermissions: options.requestedPermissions,\n shareEncryptionKeys: options.shareEncryptionKey,\n shareOwningEntityIds: ShareMetadataBehaviour.NEVER,\n shareSecretIds: options.shareSecretIds,\n },\n ])\n ),\n (x) => this.bulkShareReceipt(x)\n )\n }\n\n getDataOwnersWithAccessTo(\n entity: models.Receipt\n ): Promise<{ permissionsByDataOwnerId: { [p: string]: AccessLevelEnum }; hasUnknownAnonymousDataOwners: boolean }> {\n return this.crypto.delegationsDeAnonymization.getDataOwnersWithAccessTo({ entity, type: EntityWithDelegationTypeName.Receipt })\n }\n\n getEncryptionKeysOf(entity: models.Receipt): Promise<string[]> {\n return this.crypto.xapi.encryptionKeysOf({ entity, type: EntityWithDelegationTypeName.Receipt }, undefined)\n }\n\n createDelegationDeAnonymizationMetadata(entity: models.Receipt, delegates: string[]): Promise<void> {\n return this.crypto.delegationsDeAnonymization.createOrUpdateDeAnonymizationInfo({ entity, type: EntityWithDelegationTypeName.Receipt }, delegates)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"icc-receipt-x-api.js","sourceRoot":"","sources":["../../icc-x-api/icc-receipt-x-api.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,wCAA0C;AAG1C,kDAAiD;AAEjD,0EAAgG;AAChG,4EAAwE;AAIxE,wEAAoE;AACpE,IAAO,eAAe,GAAG,mCAAgB,CAAC,eAAe,CAAA;AAIzD,mCAA6D;AAE7D,MAAa,cAAe,SAAQ,uBAAa;IAC/C,IAAI,OAAO;QACT,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,CAAC,2BAA2B,CAAC,CAAC,EAAE,oCAA4B,CAAC,OAAO,CAAC,CAAC,CAAA;IAC7I,CAAC;IAED,YACE,IAAY,EACZ,OAAkC,EACjB,MAAqB,EACrB,YAA8B,EAC9B,cAAuB,EACxC,yBAAiD,IAAI,iDAAwB,EAAE,EAC/E,YAA2E,OAAO,MAAM,KAAK,WAAW;QACtG,CAAC,CAAC,MAAM,CAAC,KAAK;QACd,CAAC,CAAC,OAAO,IAAI,KAAK,WAAW;YAC7B,CAAC,CAAC,IAAI,CAAC,KAAK;YACZ,CAAC,CAAC,KAAK;QAET,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,sBAAsB,EAAE,SAAS,CAAC,CAAA;QAVtC,WAAM,GAAN,MAAM,CAAe;QACrB,iBAAY,GAAZ,YAAY,CAAkB;QAC9B,mBAAc,GAAd,cAAc,CAAS;QASxC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;IAClC,CAAC;IAED;;;;;;;;;;;;;OAaG;IACG,WAAW;6DACf,IAAiB,EACjB,CAAM,EACN,UAII,EAAE;;YAEN,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,OAAO,iCAC7B,CAAC,CAAC,aAAD,CAAC,cAAD,CAAC,GAAI,EAAE,CAAC,KACZ,KAAK,EAAE,mCAAmC,EAC1C,EAAE,EAAE,MAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,EAAE,mCAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,EAChD,OAAO,EAAE,MAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,OAAO,mCAAI,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,EAC3C,QAAQ,EAAE,MAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,QAAQ,mCAAI,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,EAC7C,WAAW,EAAE,MAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,WAAW,mCAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAC3G,MAAM,EAAE,MAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,MAAM,mCAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EAChE,KAAK,EAAE,MAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,KAAK,mCAAI,EAAE,EACrB,IAAI,EAAE,MAAA,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,IAAI,mCAAI,EAAE,IACnB,CAAA;YAEF,MAAM,gBAAgB,mCACjB,CAAC,OAAO,CAAC,qBAAqB,IAAI,IAAI;gBACvC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,CAAC,GAAG,CAAC,MAAA,MAAA,IAAI,CAAC,eAAe,0CAAE,GAAG,mCAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAA,MAAA,IAAI,CAAC,eAAe,0CAAE,kBAAkB,mCAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CACnI,CAAC,GACH,CAAC,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,mBAAmB,mCAAI,EAAE,CAAC,CACxC,CAAA;YACD,OAAO,IAAI,MAAM,CAAC,OAAO,CACvB,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI;iBACnB,sCAAsC,CACrC,OAAO,EACP,oCAA4B,CAAC,OAAO,EACpC,SAAS,EACT,SAAS,EACT,IAAI,EACJ,gBAAgB,EAChB,OAAO,CAAC,uBAAuB,CAChC;iBACA,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAChC,CAAA;QACH,CAAC;KAAA;IAED;;;;;;;;OAQG;IACH,UAAU,CAAC,IAAiB,EAAE,KAAa,EAAE,IAAmB,EAAE,QAAgB,EAAE,IAAiB;QACnG,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;aACnE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;aACxC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,IAAI,CAAC,EAAG,EAAE,IAAI,CAAC,GAAI,EAAE,QAAQ,EAAO,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACpJ,CAAC;IAED;;;;;;OAMG;IACG,8BAA8B,CAAC,OAAuB,EAAE,QAAgB,EAAE,UAAoC;;;YAClH,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,oCAA4B,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAC7I,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CACtB,CAAA;YACD,OAAO,MAAM,IAAI,CAAC,+BAA+B,CAAC,OAAO,CAAC,EAAG,EAAE,MAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,GAAG,mCAAI,OAAO,CAAC,GAAI,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAA;QAC7H,CAAC;KAAA;IAED;;;;;;OAMG;IACG,yBAAyB,CAAC,OAAuB,EAAE,QAAgB,EAAE,UAAoC;;YAC7G,OAAO,MAAM,IAAI,CAAC,+BAA+B,CAAC,OAAO,CAAC,EAAG,EAAE,OAAO,CAAC,GAAI,EAAE,QAAQ,EAAE,IAAA,aAAK,EAAC,UAAU,CAAC,CAAC,CAAA;QAC3G,CAAC;KAAA;IAED;;;;;;;OAOG;IACG,8BAA8B;6DAClC,OAAuB,EACvB,YAAoB,EACpB,YAA0D,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YAErF,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,iCAAiC,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;YAC1G,IAAI,CAAC,SAAS,CAAC,YAAY;gBAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,OAAO,CAAC,EAAE,GAAG,CAAC,CAAA;YAC5G,OAAO,SAAS,CAAC,IAAI,CAAA;QACvB,CAAC;KAAA;IAED;;;;;;;;;OASG;IACG,iCAAiC;6DACrC,OAAuB,EACvB,YAAoB,EACpB,YAA0D,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YAErF,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAC5C,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,oCAA4B,CAAC,OAAO,EAAE,EAC/D,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAG,EAAE,YAAY,CAAC,EAC1D,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CACpB,CAAA;QACH,CAAC;KAAA;IAED;;OAEG;IACG,cAAc,CAAC,OAAuB;;YAC1C,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,oCAA4B,CAAC,OAAO,EAAE,CAAC,CAAA;QACzG,CAAC;KAAA;IAED;;;;;;;;;;;;OAYG;IACG,SAAS;6DACb,UAAkB,EAClB,OAAuB,EACvB,UAII,EAAE;YAEN,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;QAC/D,CAAC;KAAA;IAED;;;;;;;;;;;OAWG;IACG,aAAa,CACjB,OAAuB,EACvB,SAMC;;YAED,OAAO,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAA;QAC/E,CAAC;KAAA;IAED;;;;;;;;;;;;OAYG;IACG,gBAAgB,CACpB,OAAuB,EACvB,SAMC;;YAED,8CAA8C;YAC9C,MAAM,uBAAuB,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,OAAO,EAAE,oCAA4B,CAAC,OAAO,CAAC,CAAA;YACrI,MAAM,aAAa,GAAG,uBAAuB,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;YAC3G,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAChE;gBACE,MAAM,EAAE,aAAa;gBACrB,IAAI,EAAE,oCAA4B,CAAC,OAAO;aAC3C,EACD,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;gBACvD,UAAU;gBACV;oBACE,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;oBAClD,mBAAmB,EAAE,OAAO,CAAC,kBAAkB;oBAC/C,oBAAoB,EAAE,+CAAsB,CAAC,KAAK;oBAClD,cAAc,EAAE,OAAO,CAAC,cAAc;iBACvC;aACF,CAAC,CACH,EACD,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAChC,CAAA;QACH,CAAC;KAAA;IAED;;;;OAIG;IACH,yBAAyB,CACvB,MAAsB;QAEtB,OAAO,IAAI,CAAC,MAAM,CAAC,0BAA0B,CAAC,yBAAyB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,oCAA4B,CAAC,OAAO,EAAE,CAAC,CAAA;IACjI,CAAC;IAED;;;;OAIG;IACH,mBAAmB,CAAC,MAAsB;QACxC,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,oCAA4B,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAA;IAC7G,CAAC;IAED;;;;;OAKG;IACH,uCAAuC,CAAC,MAAsB,EAAE,SAAmB;QACjF,OAAO,IAAI,CAAC,MAAM,CAAC,0BAA0B,CAAC,iCAAiC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,oCAA4B,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAA;IACpJ,CAAC;CACF;AApSD,wCAoSC","sourcesContent":["import { IccReceiptApi } from '../icc-api'\nimport { IccCryptoXApi } from './icc-crypto-x-api'\nimport * as _ from 'lodash'\nimport * as models from '../icc-api/model/models'\nimport { IccDataOwnerXApi } from './icc-data-owner-x-api'\nimport { AuthenticationProvider, NoAuthenticationProvider } from './auth/AuthenticationProvider'\nimport { ShareMetadataBehaviour } from './crypto/ShareMetadataBehaviour'\nimport { ShareResult } from './utils/ShareResult'\nimport { EntityShareRequest } from '../icc-api/model/requests/EntityShareRequest'\nimport RequestedPermissionEnum = EntityShareRequest.RequestedPermissionEnum\nimport { SecureDelegation } from '../icc-api/model/SecureDelegation'\nimport AccessLevelEnum = SecureDelegation.AccessLevelEnum\nimport { XHR } from '../icc-api/api/XHR'\nimport { EncryptedEntityXApi } from './basexapi/EncryptedEntityXApi'\nimport { MaintenanceTask } from '../icc-api/model/models'\nimport { EntityWithDelegationTypeName, ua2ab } from './utils'\n\nexport class IccReceiptXApi extends IccReceiptApi implements EncryptedEntityXApi<models.Receipt> {\n get headers(): Promise<Array<XHR.Header>> {\n return super.headers.then((h) => this.crypto.accessControlKeysHeaders.addAccessControlKeysHeaders(h, EntityWithDelegationTypeName.Receipt))\n }\n\n constructor(\n host: string,\n headers: { [key: string]: string },\n private readonly crypto: IccCryptoXApi,\n private readonly dataOwnerApi: IccDataOwnerXApi,\n private readonly autofillAuthor: boolean,\n authenticationProvider: AuthenticationProvider = new NoAuthenticationProvider(),\n fetchImpl: (input: RequestInfo, init?: RequestInit) => Promise<Response> = typeof window !== 'undefined'\n ? window.fetch\n : typeof self !== 'undefined'\n ? self.fetch\n : fetch\n ) {\n super(host, headers, authenticationProvider, fetchImpl)\n this.dataOwnerApi = dataOwnerApi\n }\n\n /**\n * Creates a new instance of receipt with initialised encryption metadata (not in the database).\n * @param user the current user.\n * @param r initialised data for the receipt. Metadata such as id, creation data, etc. will be automatically initialised, but you can specify\n * other kinds of data or overwrite generated metadata with this. You can't specify encryption metadata.\n * @param options optional parameters:\n * - additionalDelegates: delegates which will have access to the entity in addition to the current data owner and delegates from the\n * auto-delegations. Must be an object which associates each data owner id with the access level to give to that data owner. May overlap with\n * auto-delegations, in such case the access level specified here will be used.\n * - ignoreAutoDelegations: if true the data won't be shared with the autodelegations of the user, but only with additional delegates\n * - alternateRootDelegation: by default a new entity is created with a root delegation from self to self. In keyless mode this is not possible,\n * and instead the root delegation will be from self to another. You have to specify which delegate will be part of the root delegation.\n * @return a new instance of receipt.\n */\n async newInstance(\n user: models.User,\n r: any,\n options: {\n additionalDelegates?: { [dataOwnerId: string]: AccessLevelEnum }\n ignoreAutoDelegations?: boolean\n alternateRootDelegation?: string\n } = {}\n ): Promise<models.Receipt> {\n const receipt = new models.Receipt({\n ...(r ?? {}),\n _type: 'org.taktik.icure.entities.Receipt',\n id: r?.id ?? this.crypto.primitives.randomUuid(),\n created: r?.created ?? new Date().getTime(),\n modified: r?.modified ?? new Date().getTime(),\n responsible: r?.responsible ?? (this.autofillAuthor ? this.dataOwnerApi.getDataOwnerIdOf(user) : undefined),\n author: r?.author ?? (this.autofillAuthor ? user.id : undefined),\n codes: r?.codes ?? [],\n tags: r?.tags ?? [],\n })\n\n const extraDelegations = {\n ...(options.ignoreAutoDelegations == true\n ? {}\n : Object.fromEntries(\n [...(user.autoDelegations?.all ?? []), ...(user.autoDelegations?.medicalInformation ?? [])].map((d) => [d, AccessLevelEnum.WRITE])\n )),\n ...(options?.additionalDelegates ?? {}),\n }\n return new models.Receipt(\n await this.crypto.xapi\n .entityWithInitialisedEncryptedMetadata(\n receipt,\n EntityWithDelegationTypeName.Receipt,\n undefined,\n undefined,\n true,\n extraDelegations,\n options.alternateRootDelegation\n )\n .then((x) => x.updatedEntity)\n )\n }\n\n /**\n * Creates a new receipt linked to a document and optionally attaches a blob to it.\n * @param user the current user.\n * @param docId the id of the document this receipt refers to.\n * @param refs an array of reference strings to associate with the receipt.\n * @param blobType the type of the blob attachment.\n * @param blob the binary content to attach; if empty (byteLength == 0), no attachment is set.\n * @return the created receipt, with the attachment set if the blob was non-empty.\n */\n logReceipt(user: models.User, docId: string, refs: Array<string>, blobType: string, blob: ArrayBuffer) {\n return this.newInstance(user, { documentId: docId, references: refs })\n .then((rcpt) => this.createReceipt(rcpt))\n .then((rcpt) => (blob.byteLength != 0 ? this.setReceiptAttachmentForBlobType(rcpt.id!, rcpt.rev!, blobType, <any>blob) : Promise.resolve(rcpt)))\n }\n\n /**\n * Adds an attachment to a receipt, encrypting it on client side using the encryption keys of the provided receipt.\n * @param receipt a receipt.\n * @param blobType the type of the attachment.\n * @param attachment a attachment for the receipt.\n * @return the updated receipt.\n */\n async encryptAndSetReceiptAttachment(receipt: models.Receipt, blobType: string, attachment: ArrayBuffer | Uint8Array): Promise<models.Receipt> {\n const { encryptedData, updatedEntity } = await this.crypto.xapi.encryptDataOf(receipt, EntityWithDelegationTypeName.Receipt, attachment, (r) =>\n this.modifyReceipt(r)\n )\n return await this.setReceiptAttachmentForBlobType(receipt.id!, updatedEntity?.rev ?? receipt.rev!, blobType, encryptedData)\n }\n\n /**\n * Adds an unencrypted attachment to a receipt.\n * @param receipt a receipt.\n * @param blobType the type of the attachment.\n * @param attachment a attachment for the receipt.\n * @return the updated receipt.\n */\n async setClearReceiptAttachment(receipt: models.Receipt, blobType: string, attachment: ArrayBuffer | Uint8Array): Promise<models.Receipt> {\n return await this.setReceiptAttachmentForBlobType(receipt.id!, receipt.rev!, blobType, ua2ab(attachment))\n }\n\n /**\n * Gets the attachment of a receipt and tries to decrypt it using the encryption keys of the receipt.\n * @param receipt a receipt.\n * @param attachmentId id of the attachment of this receipt to retrieve.\n * @param validator optionally a validator function which checks if the decryption was successful. In cases where the receipt has many encryption\n * keys and it is unclear which one should be used this function can help to detect bad decryptions.\n * @return the decrypted attachment, if it could be decrypted, else the encrypted attachment.\n */\n async getAndDecryptReceiptAttachment(\n receipt: models.Receipt,\n attachmentId: string,\n validator: (decrypted: ArrayBuffer) => Promise<boolean> = () => Promise.resolve(true)\n ): Promise<ArrayBuffer> {\n const retrieved = await this.getAndTryDecryptReceiptAttachment(receipt, attachmentId, (x) => validator(x))\n if (!retrieved.wasDecrypted) throw new Error(`No valid key found to decrypt data of receipt ${receipt.id}.`)\n return retrieved.data\n }\n\n /**\n * Gets the attachment of a receipt and tries to decrypt it using the encryption keys of the receipt.\n * @param receipt a receipt.\n * @param attachmentId id of the attachment of this receipt to retrieve.\n * @param validator optionally a validator function which checks if the decryption was successful. In cases where the receipt has many encryption\n * keys and it is unclear which one should be used this function can help to detect bad decryptions.\n * @return an object containing:\n * - data: the decrypted attachment, if it could be decrypted, else the encrypted attachment.\n * - wasDecrypted: if the data was successfully decrypted or not\n */\n async getAndTryDecryptReceiptAttachment(\n receipt: models.Receipt,\n attachmentId: string,\n validator: (decrypted: ArrayBuffer) => Promise<boolean> = () => Promise.resolve(true)\n ): Promise<{ data: ArrayBuffer; wasDecrypted: boolean }> {\n return await this.crypto.xapi.tryDecryptDataOf(\n { entity: receipt, type: EntityWithDelegationTypeName.Receipt },\n await this.getReceiptAttachment(receipt.id!, attachmentId),\n (x) => validator(x)\n )\n }\n\n /**\n * @return if the logged data owner has write access to the content of the given receipt\n */\n async hasWriteAccess(receipt: models.Receipt): Promise<boolean> {\n return this.crypto.xapi.hasWriteAccess({ entity: receipt, type: EntityWithDelegationTypeName.Receipt })\n }\n\n /**\n * Share an existing receipt with other data owners, allowing them to access the non-encrypted data of the receipt and optionally also\n * the encrypted content, with read-only or read-write permissions.\n * @param delegateId the id of the data owner which will be granted access to the receipt.\n * @param receipt the receipt to share.\n * @param options optional parameters to customize the sharing behaviour:\n * - shareSecretIds: specifies which secret ids of the entity should be shared. If not provided all secret ids available to the current user will be shared\n * - shareEncryptionKey: specifies if the encryption key of the access log should be shared with the delegate, giving access to all encrypted\n * content of the entity, excluding other encrypted metadata (defaults to {@link ShareMetadataBehaviour.IF_AVAILABLE}). Note that by default a\n * receipt does not have encrypted content.\n * - requestedPermissions: the requested permissions for the delegate, defaults to {@link RequestedPermissionEnum.MAX_WRITE}.\n * @return the updated entity\n */\n async shareWith(\n delegateId: string,\n receipt: models.Receipt,\n options: {\n shareSecretIds?: string[]\n requestedPermissions?: RequestedPermissionEnum\n shareEncryptionKey?: ShareMetadataBehaviour // Defaults to ShareMetadataBehaviour.IF_AVAILABLE\n } = {}\n ): Promise<models.Receipt> {\n return this.shareWithMany(receipt, { [delegateId]: options })\n }\n\n /**\n * Share an existing receipt with other data owners, allowing them to access the non-encrypted data of the receipt and optionally also\n * the encrypted content, with read-only or read-write permissions.\n * @param receipt the receipt to share.\n * @param delegates associates the id of data owners which will be granted access to the entity, to the following sharing options:\n * - shareSecretIds: specifies which secret ids of the entity should be shared. If not provided all secret ids available to the current user will be shared\n * - shareEncryptionKey: specifies if the encryption key of the access log should be shared with the delegate, giving access to all encrypted\n * content of the entity, excluding other encrypted metadata (defaults to {@link ShareMetadataBehaviour.IF_AVAILABLE}). Note that by default a\n * receipt does not have encrypted content.\n * - requestedPermissions: the requested permissions for the delegate, defaults to {@link RequestedPermissionEnum.MAX_WRITE}.\n * @return the updated entity\n */\n async shareWithMany(\n receipt: models.Receipt,\n delegates: {\n [delegateId: string]: {\n shareSecretIds?: string[]\n requestedPermissions?: RequestedPermissionEnum\n shareEncryptionKey?: ShareMetadataBehaviour // Defaults to ShareMetadataBehaviour.IF_AVAILABLE\n }\n }\n ): Promise<models.Receipt> {\n return (await this.tryShareWithMany(receipt, delegates)).updatedEntityOrThrow\n }\n\n /**\n * Share an existing receipt with other data owners, allowing them to access the non-encrypted data of the receipt and optionally also\n * the encrypted content, with read-only or read-write permissions.\n * @param receipt the receipt to share.\n * @param delegates associates the id of data owners which will be granted access to the entity, to the following sharing options:\n * - shareSecretIds: specifies which secret ids of the entity should be shared. If not provided all secret ids available to the current user will be shared\n * - shareEncryptionKey: specifies if the encryption key of the access log should be shared with the delegate, giving access to all encrypted\n * content of the entity, excluding other encrypted metadata (defaults to {@link ShareMetadataBehaviour.IF_AVAILABLE}). Note that by default a\n * receipt does not have encrypted content.\n * - requestedPermissions: the requested permissions for the delegate, defaults to {@link RequestedPermissionEnum.MAX_WRITE}.\n * @return a promise which will contain the result of the operation: the updated entity if the operation was successful or details of the error if\n * the operation failed.\n */\n async tryShareWithMany(\n receipt: models.Receipt,\n delegates: {\n [delegateId: string]: {\n shareSecretIds?: string[]\n requestedPermissions?: RequestedPermissionEnum\n shareEncryptionKey?: ShareMetadataBehaviour // Defaults to ShareMetadataBehaviour.IF_AVAILABLE\n }\n }\n ): Promise<ShareResult<models.Receipt>> {\n // All entities should have an encryption key.\n const entityWithEncryptionKey = await this.crypto.xapi.ensureEncryptionKeysInitialised(receipt, EntityWithDelegationTypeName.Receipt)\n const updatedEntity = entityWithEncryptionKey ? await this.modifyReceipt(entityWithEncryptionKey) : receipt\n return this.crypto.xapi.simpleShareOrUpdateEncryptedEntityMetadata(\n {\n entity: updatedEntity,\n type: EntityWithDelegationTypeName.Receipt,\n },\n Object.fromEntries(\n Object.entries(delegates).map(([delegateId, options]) => [\n delegateId,\n {\n requestedPermissions: options.requestedPermissions,\n shareEncryptionKeys: options.shareEncryptionKey,\n shareOwningEntityIds: ShareMetadataBehaviour.NEVER,\n shareSecretIds: options.shareSecretIds,\n },\n ])\n ),\n (x) => this.bulkShareReceipt(x)\n )\n }\n\n /**\n * Retrieves the data owners that have access to the given receipt, along with their access levels.\n * @param entity the receipt.\n * @return an object containing a map of data owner ids to their access levels, and a flag indicating if there are unknown anonymous data owners.\n */\n getDataOwnersWithAccessTo(\n entity: models.Receipt\n ): Promise<{ permissionsByDataOwnerId: { [p: string]: AccessLevelEnum }; hasUnknownAnonymousDataOwners: boolean }> {\n return this.crypto.delegationsDeAnonymization.getDataOwnersWithAccessTo({ entity, type: EntityWithDelegationTypeName.Receipt })\n }\n\n /**\n * Retrieves the encryption keys of the given receipt.\n * @param entity the receipt.\n * @return the encryption key ids.\n */\n getEncryptionKeysOf(entity: models.Receipt): Promise<string[]> {\n return this.crypto.xapi.encryptionKeysOf({ entity, type: EntityWithDelegationTypeName.Receipt }, undefined)\n }\n\n /**\n * Creates or updates de-anonymization metadata for the given receipt, allowing the specified delegates to\n * identify the data owners that have access to it.\n * @param entity the receipt.\n * @param delegates the data owner ids for which to create de-anonymization metadata.\n */\n createDelegationDeAnonymizationMetadata(entity: models.Receipt, delegates: string[]): Promise<void> {\n return this.crypto.delegationsDeAnonymization.createOrUpdateDeAnonymizationInfo({ entity, type: EntityWithDelegationTypeName.Receipt }, delegates)\n }\n}\n"]}
|
|
@@ -12,9 +12,34 @@ export declare class IccUserXApi extends IccUserApi {
|
|
|
12
12
|
constructor(host: string, headers: {
|
|
13
13
|
[key: string]: string;
|
|
14
14
|
}, authenticationProvider: AuthenticationProvider | undefined, authApi: IccAuthApi, fetchImpl?: (input: RequestInfo, init?: RequestInit) => Promise<Response>);
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves the currently logged-in user. Uses a cached version by default to avoid redundant API calls.
|
|
17
|
+
* @param bypassCache if true, forces a fresh fetch from the server and updates the cache; otherwise returns the cached user if available.
|
|
18
|
+
* @return the current user.
|
|
19
|
+
*/
|
|
15
20
|
getCurrentUser(bypassCache?: boolean): Promise<User>;
|
|
21
|
+
/**
|
|
22
|
+
* Modifies an existing user. If the user being modified is the current user, the local cache is updated accordingly.
|
|
23
|
+
* Handles 409 conflict errors by re-fetching the latest revision and retrying when the only server-side changes
|
|
24
|
+
* are to authenticationTokens or rev.
|
|
25
|
+
* @param body the user with updated fields to persist.
|
|
26
|
+
* @return the modified user as returned by the server.
|
|
27
|
+
*/
|
|
16
28
|
modifyUser(body?: User): Promise<User>;
|
|
29
|
+
/**
|
|
30
|
+
* Subscribes to real-time user events using a WebSocket connection.
|
|
31
|
+
* @param eventTypes the types of events to listen for (e.g. 'CREATE', 'UPDATE', 'DELETE').
|
|
32
|
+
* @param filter an optional filter to restrict which user events trigger the callback.
|
|
33
|
+
* @param eventFired the callback function invoked when a matching user event is received.
|
|
34
|
+
* @param options optional subscription configuration such as connection parameters and retry behaviour.
|
|
35
|
+
* @return a connection object that can be used to manage the WebSocket subscription lifecycle.
|
|
36
|
+
*/
|
|
17
37
|
subscribeToUserEvents(eventTypes: ('CREATE' | 'UPDATE' | 'DELETE')[], filter: AbstractFilter<User> | undefined, eventFired: (user: User) => Promise<void>, options?: SubscriptionOptions): Promise<Connection>;
|
|
38
|
+
/**
|
|
39
|
+
* Checks whether the given password is valid for the currently logged-in user by attempting authentication.
|
|
40
|
+
* @param password the password to verify.
|
|
41
|
+
* @return true if the password is valid, false otherwise.
|
|
42
|
+
*/
|
|
18
43
|
checkPassword(password: string): Promise<boolean>;
|
|
19
44
|
private getGroupAndUserIdFromToken;
|
|
20
45
|
}
|
|
@@ -27,6 +27,11 @@ class IccUserXApi extends IccUserApi_1.IccUserApi {
|
|
|
27
27
|
this.authApi = authApi;
|
|
28
28
|
this.fetchImpl = fetchImpl;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Retrieves the currently logged-in user. Uses a cached version by default to avoid redundant API calls.
|
|
32
|
+
* @param bypassCache if true, forces a fresh fetch from the server and updates the cache; otherwise returns the cached user if available.
|
|
33
|
+
* @return the current user.
|
|
34
|
+
*/
|
|
30
35
|
getCurrentUser(bypassCache = false) {
|
|
31
36
|
var _a;
|
|
32
37
|
if (bypassCache)
|
|
@@ -34,6 +39,13 @@ class IccUserXApi extends IccUserApi_1.IccUserApi {
|
|
|
34
39
|
else
|
|
35
40
|
return (_a = this.cachedCurrentUser) !== null && _a !== void 0 ? _a : (this.cachedCurrentUser = super.getCurrentUser());
|
|
36
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Modifies an existing user. If the user being modified is the current user, the local cache is updated accordingly.
|
|
44
|
+
* Handles 409 conflict errors by re-fetching the latest revision and retrying when the only server-side changes
|
|
45
|
+
* are to authenticationTokens or rev.
|
|
46
|
+
* @param body the user with updated fields to persist.
|
|
47
|
+
* @return the modified user as returned by the server.
|
|
48
|
+
*/
|
|
37
49
|
modifyUser(body) {
|
|
38
50
|
const _super = Object.create(null, {
|
|
39
51
|
modifyUser: { get: () => super.modifyUser },
|
|
@@ -66,12 +78,25 @@ class IccUserXApi extends IccUserApi_1.IccUserApi {
|
|
|
66
78
|
return _super.modifyUser.call(this, body);
|
|
67
79
|
});
|
|
68
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Subscribes to real-time user events using a WebSocket connection.
|
|
83
|
+
* @param eventTypes the types of events to listen for (e.g. 'CREATE', 'UPDATE', 'DELETE').
|
|
84
|
+
* @param filter an optional filter to restrict which user events trigger the callback.
|
|
85
|
+
* @param eventFired the callback function invoked when a matching user event is received.
|
|
86
|
+
* @param options optional subscription configuration such as connection parameters and retry behaviour.
|
|
87
|
+
* @return a connection object that can be used to manage the WebSocket subscription lifecycle.
|
|
88
|
+
*/
|
|
69
89
|
subscribeToUserEvents(eventTypes_1, filter_1, eventFired_1) {
|
|
70
90
|
return __awaiter(this, arguments, void 0, function* (eventTypes, filter, eventFired, options = {}) {
|
|
71
91
|
const rs = yield (0, utils_1.subscribeToEntityEvents)(this.host, this.authApi, 'User', eventTypes, filter, eventFired, options);
|
|
72
92
|
return new Connection_1.ConnectionImpl(rs);
|
|
73
93
|
});
|
|
74
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Checks whether the given password is valid for the currently logged-in user by attempting authentication.
|
|
97
|
+
* @param password the password to verify.
|
|
98
|
+
* @return true if the password is valid, false otherwise.
|
|
99
|
+
*/
|
|
75
100
|
checkPassword(password) {
|
|
76
101
|
return __awaiter(this, void 0, void 0, function* () {
|
|
77
102
|
var _a;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icc-user-x-api.js","sourceRoot":"","sources":["../../icc-x-api/icc-user-x-api.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,0DAAsD;AACtD,0EAAgG;AAGhG,4DAAwE;AACxE,mCAA2E;AAE3E,+DAAuD;AACvD,4CAAwC;AACxC,IAAO,QAAQ,GAAG,SAAG,CAAC,QAAQ,CAAA;AAE9B,MAAa,WAAY,SAAQ,uBAAU;IAIzC,YACE,IAAY,EACZ,OAAkC,EAClC,yBAAiD,IAAI,iDAAwB,EAAE,EAC9D,OAAmB,EACpC,YAA2E,OAAO,MAAM,KAAK,WAAW;QACtG,CAAC,CAAC,MAAM,CAAC,KAAK;QACd,CAAC,CAAC,OAAO,IAAI,KAAK,WAAW;YAC7B,CAAC,CAAC,IAAI,CAAC,KAAK;YACZ,CAAC,CAAC,KAAK;QAET,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,sBAAsB,EAAE,SAAS,CAAC,CAAA;QAPtC,YAAO,GAAP,OAAO,CAAY;QAQpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;IAC5B,CAAC;IAED,cAAc,CAAC,cAAuB,KAAK;;QACzC,IAAI,WAAW;YAAE,OAAO,CAAC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;;YACpE,OAAO,MAAA,IAAI,CAAC,iBAAiB,mCAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,CAAA;IACzF,CAAC;
|
|
1
|
+
{"version":3,"file":"icc-user-x-api.js","sourceRoot":"","sources":["../../icc-x-api/icc-user-x-api.ts"],"names":[],"mappings":"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","sourcesContent":["import { IccUserApi } from '../icc-api/api/IccUserApi'\nimport { AuthenticationProvider, NoAuthenticationProvider } from './auth/AuthenticationProvider'\nimport { AbstractFilter } from './filters/filters'\nimport { User } from '../icc-api/model/User'\nimport { Connection, ConnectionImpl } from '../icc-api/model/Connection'\nimport { a2b, subscribeToEntityEvents, SubscriptionOptions } from './utils'\nimport { IccAuthApi } from '../icc-api'\nimport { objectEquals } from './utils/collection-utils'\nimport { XHR } from '../icc-api/api/XHR'\nimport XHRError = XHR.XHRError\n\nexport class IccUserXApi extends IccUserApi {\n fetchImpl: (input: RequestInfo, init?: RequestInit) => Promise<Response>\n private cachedCurrentUser: Promise<User> | undefined\n\n constructor(\n host: string,\n headers: { [key: string]: string },\n authenticationProvider: AuthenticationProvider = new NoAuthenticationProvider(),\n private readonly authApi: IccAuthApi,\n fetchImpl: (input: RequestInfo, init?: RequestInit) => Promise<Response> = typeof window !== 'undefined'\n ? window.fetch\n : typeof self !== 'undefined'\n ? self.fetch\n : fetch\n ) {\n super(host, headers, authenticationProvider, fetchImpl)\n this.fetchImpl = fetchImpl\n }\n\n /**\n * Retrieves the currently logged-in user. Uses a cached version by default to avoid redundant API calls.\n * @param bypassCache if true, forces a fresh fetch from the server and updates the cache; otherwise returns the cached user if available.\n * @return the current user.\n */\n getCurrentUser(bypassCache: boolean = false): Promise<User> {\n if (bypassCache) return (this.cachedCurrentUser = super.getCurrentUser())\n else return this.cachedCurrentUser ?? (this.cachedCurrentUser = super.getCurrentUser())\n }\n\n /**\n * Modifies an existing user. If the user being modified is the current user, the local cache is updated accordingly.\n * Handles 409 conflict errors by re-fetching the latest revision and retrying when the only server-side changes\n * are to authenticationTokens or rev.\n * @param body the user with updated fields to persist.\n * @return the modified user as returned by the server.\n */\n async modifyUser(body?: User): Promise<User> {\n //If we do not load the current user, we cannot know if the modification is on the current user\n await this.getCurrentUser()\n if (this.cachedCurrentUser && (await this.cachedCurrentUser).id === body?.id) {\n try {\n const modifiedUser = await super.modifyUser(body).catch(async (e) => {\n //It is\n if (e.statusCode === 409) {\n let userInDb = await super.getCurrentUser()\n if (objectEquals((await this.cachedCurrentUser)!, userInDb, ['authenticationTokens', 'rev'])) {\n return await super.modifyUser({ ...body, rev: userInDb.rev, authenticationTokens: userInDb.authenticationTokens })\n }\n }\n throw e\n })\n this.cachedCurrentUser = Promise.resolve(modifiedUser)\n return modifiedUser\n } catch (e) {\n this.cachedCurrentUser = undefined\n throw e\n }\n } else return super.modifyUser(body)\n }\n\n /**\n * Subscribes to real-time user events using a WebSocket connection.\n * @param eventTypes the types of events to listen for (e.g. 'CREATE', 'UPDATE', 'DELETE').\n * @param filter an optional filter to restrict which user events trigger the callback.\n * @param eventFired the callback function invoked when a matching user event is received.\n * @param options optional subscription configuration such as connection parameters and retry behaviour.\n * @return a connection object that can be used to manage the WebSocket subscription lifecycle.\n */\n async subscribeToUserEvents(\n eventTypes: ('CREATE' | 'UPDATE' | 'DELETE')[],\n filter: AbstractFilter<User> | undefined,\n eventFired: (user: User) => Promise<void>,\n options: SubscriptionOptions = {}\n ): Promise<Connection> {\n const rs = await subscribeToEntityEvents(this.host, this.authApi, 'User', eventTypes, filter, eventFired, options)\n return new ConnectionImpl(rs)\n }\n\n /**\n * Checks whether the given password is valid for the currently logged-in user by attempting authentication.\n * @param password the password to verify.\n * @return true if the password is valid, false otherwise.\n */\n async checkPassword(password: string): Promise<boolean> {\n const userInfo = await this.getGroupAndUserIdFromToken()\n if (!!userInfo) {\n console.log(this.authApi)\n const loginUserId = !!userInfo.groupId ? `${userInfo.groupId}/${userInfo.userId}` : userInfo.userId\n try {\n return (await this.authApi.login({ username: loginUserId, password: password })).successful ?? false\n } catch (e) {\n return e instanceof XHRError && e.statusCode == 417\n }\n }\n throw Error('Could not get current group and user from jwt')\n }\n\n private async getGroupAndUserIdFromToken(): Promise<{ groupId: string | undefined; userId: string } | undefined> {\n const token = (await this.authenticationProvider.getIcureTokens())?.token\n if (!token) return undefined\n const splitToken = token.split('.')\n if (splitToken.length != 3) return undefined\n try {\n const tokenString = a2b(splitToken[1])\n const parsedClaims = JSON.parse(tokenString)\n if (!!parsedClaims['u']) {\n return { groupId: parsedClaims['g'], userId: parsedClaims['u'] }\n } else return undefined\n } catch {\n return undefined\n }\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -17,13 +17,16 @@ const icc_api_1 = require("../../icc-api");
|
|
|
17
17
|
const Patient_1 = require("../../icc-api/model/Patient");
|
|
18
18
|
const crypto_1 = require("crypto");
|
|
19
19
|
const Form_1 = require("../../icc-api/model/Form");
|
|
20
|
+
const FormTemplate_1 = require("../../icc-api/model/FormTemplate");
|
|
21
|
+
const CodeStub_1 = require("../../icc-api/model/CodeStub");
|
|
20
22
|
const chai_1 = require("chai");
|
|
21
23
|
var initApi = test_utils_1.TestUtils.initApi;
|
|
22
24
|
const types_1 = require("@icure/test-setup/types");
|
|
23
25
|
const AuthenticationProvider_1 = require("../../icc-x-api/auth/AuthenticationProvider");
|
|
26
|
+
const IdWithRev_1 = require("../../icc-api/model/IdWithRev");
|
|
24
27
|
(0, test_utils_1.setLocalStorage)(fetch);
|
|
25
28
|
let env;
|
|
26
|
-
describe('icc-
|
|
29
|
+
describe('icc-form-x-api Tests', () => {
|
|
27
30
|
(0, mocha_1.before)(function () {
|
|
28
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
29
32
|
this.timeout(600000);
|
|
@@ -94,5 +97,266 @@ describe('icc-calendar-item-x-api Tests', () => {
|
|
|
94
97
|
const retrieved = yield api2.formApi.getForm(entity.id);
|
|
95
98
|
(0, chai_1.expect)((yield api2.formApi.decryptPatientIdOf(retrieved))[0]).to.equal(samplePatient.id);
|
|
96
99
|
}));
|
|
100
|
+
it('Tests for Form Templates', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
|
+
// Given
|
|
102
|
+
const { formApi, userApi } = yield initApi(env, test_utils_1.hcp1Username);
|
|
103
|
+
const guid = (0, crypto_1.randomUUID)();
|
|
104
|
+
const specialtyCode = 'SPECIALTY-' + (0, crypto_1.randomUUID)();
|
|
105
|
+
const user = yield userApi.getCurrentUser();
|
|
106
|
+
const formTemplateToCreate = new FormTemplate_1.FormTemplate({
|
|
107
|
+
id: (0, crypto_1.randomUUID)(),
|
|
108
|
+
guid: guid,
|
|
109
|
+
author: user.id,
|
|
110
|
+
name: 'My Test Template',
|
|
111
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
112
|
+
descr: 'Description of the template',
|
|
113
|
+
});
|
|
114
|
+
// Create
|
|
115
|
+
const createdTemplate = yield formApi.createFormTemplate(formTemplateToCreate);
|
|
116
|
+
(0, chai_1.expect)(createdTemplate.id).to.not.be.undefined;
|
|
117
|
+
(0, chai_1.expect)(createdTemplate.guid).to.equal(guid);
|
|
118
|
+
(0, chai_1.expect)(createdTemplate.name).to.equal('My Test Template');
|
|
119
|
+
// Get
|
|
120
|
+
const retrievedTemplate = yield formApi.getFormTemplate(createdTemplate.id);
|
|
121
|
+
(0, chai_1.expect)(retrievedTemplate.id).to.equal(createdTemplate.id);
|
|
122
|
+
// Find all
|
|
123
|
+
const allTemplates = yield formApi.findFormTemplates();
|
|
124
|
+
(0, chai_1.expect)(allTemplates.map((t) => t.id)).to.include(createdTemplate.id);
|
|
125
|
+
// Find by specialty
|
|
126
|
+
const templatesBySpecialty = yield formApi.findFormTemplatesBySpeciality(specialtyCode);
|
|
127
|
+
(0, chai_1.expect)(templatesBySpecialty.map((t) => t.id)).to.include(createdTemplate.id);
|
|
128
|
+
(0, chai_1.expect)(templatesBySpecialty.length).to.be.greaterThan(0);
|
|
129
|
+
// Get by GUID (using getFormTemplatesByGuid)
|
|
130
|
+
const templatesByGuid = yield formApi.getFormTemplatesByGuid(guid, specialtyCode);
|
|
131
|
+
(0, chai_1.expect)(templatesByGuid.map((t) => t.id)).to.include(createdTemplate.id);
|
|
132
|
+
// Update
|
|
133
|
+
createdTemplate.name = 'Updated Name';
|
|
134
|
+
const updatedTemplate = yield formApi.updateFormTemplate(createdTemplate.id, createdTemplate);
|
|
135
|
+
(0, chai_1.expect)(updatedTemplate.name).to.equal('Updated Name');
|
|
136
|
+
// Delete
|
|
137
|
+
yield formApi.deleteFormTemplate(createdTemplate.id);
|
|
138
|
+
try {
|
|
139
|
+
yield formApi.getFormTemplate(createdTemplate.id);
|
|
140
|
+
chai_1.assert.fail('Should have thrown an error');
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
// Expected
|
|
144
|
+
}
|
|
145
|
+
}));
|
|
146
|
+
(0, test_utils_1.describeNoLite)('Form Templates in Group Tests', () => {
|
|
147
|
+
it('should create, find, update and delete form templates in a group', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
148
|
+
// Given
|
|
149
|
+
const { formApi, userApi } = yield initApi(env);
|
|
150
|
+
const currentUser = yield userApi.getCurrentUser();
|
|
151
|
+
const guid = (0, crypto_1.randomUUID)();
|
|
152
|
+
const specialtyCode = 'SPECIALTY-' + (0, crypto_1.randomUUID)();
|
|
153
|
+
// Use the existing test group ID
|
|
154
|
+
const groupId = env.testGroupId;
|
|
155
|
+
const formTemplateToCreate = new FormTemplate_1.FormTemplate({
|
|
156
|
+
id: (0, crypto_1.randomUUID)(),
|
|
157
|
+
guid: guid,
|
|
158
|
+
author: currentUser.id,
|
|
159
|
+
name: 'My Group Template',
|
|
160
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
161
|
+
descr: 'Description of the group template',
|
|
162
|
+
});
|
|
163
|
+
// Create In Group
|
|
164
|
+
const createdTemplate = yield formApi.createFormTemplateInGroup(groupId, formTemplateToCreate);
|
|
165
|
+
(0, chai_1.expect)(createdTemplate.id).to.not.be.undefined;
|
|
166
|
+
(0, chai_1.expect)(createdTemplate.guid).to.equal(guid);
|
|
167
|
+
if (createdTemplate.group) {
|
|
168
|
+
(0, chai_1.expect)(createdTemplate.group.guid).to.equal(groupId);
|
|
169
|
+
}
|
|
170
|
+
// Get In Group
|
|
171
|
+
const templatesInGroup = yield formApi.getFormTemplatesByUserInGroup(groupId, currentUser.id);
|
|
172
|
+
(0, chai_1.expect)(templatesInGroup.map((t) => t.id)).to.include(createdTemplate.id);
|
|
173
|
+
// Update In Group
|
|
174
|
+
createdTemplate.name = 'Updated Group Name';
|
|
175
|
+
const updatedTemplate = yield formApi.updateFormTemplateInGroup(groupId, createdTemplate.id, createdTemplate);
|
|
176
|
+
(0, chai_1.expect)(updatedTemplate.name).to.equal('Updated Group Name');
|
|
177
|
+
// Delete In Group
|
|
178
|
+
yield formApi.deleteFormTemplateInGroup(groupId, updatedTemplate.id, updatedTemplate.rev);
|
|
179
|
+
// Verify deletion
|
|
180
|
+
const templatesInGroupAfterDelete = yield formApi.getFormTemplatesByUserInGroup(groupId, currentUser.id);
|
|
181
|
+
(0, chai_1.expect)(templatesInGroupAfterDelete.map((t) => t.id)).to.not.include(createdTemplate.id);
|
|
182
|
+
}));
|
|
183
|
+
});
|
|
184
|
+
(0, test_utils_1.describeNoLite)('Form Templates Batch Operations in Group Tests', () => {
|
|
185
|
+
it('should create, get, and modify multiple form templates in a group (batch)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
186
|
+
// Given
|
|
187
|
+
const { formApi, userApi } = yield initApi(env);
|
|
188
|
+
const currentUser = yield userApi.getCurrentUser();
|
|
189
|
+
const groupId = env.testGroupId;
|
|
190
|
+
const specialtyCode = 'SPECIALTY-' + (0, crypto_1.randomUUID)();
|
|
191
|
+
// Create multiple templates
|
|
192
|
+
const templatesToCreate = [
|
|
193
|
+
new FormTemplate_1.FormTemplate({
|
|
194
|
+
id: (0, crypto_1.randomUUID)(),
|
|
195
|
+
guid: (0, crypto_1.randomUUID)(),
|
|
196
|
+
author: currentUser.id,
|
|
197
|
+
name: 'Batch Template 1',
|
|
198
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
199
|
+
descr: 'First batch template',
|
|
200
|
+
}),
|
|
201
|
+
new FormTemplate_1.FormTemplate({
|
|
202
|
+
id: (0, crypto_1.randomUUID)(),
|
|
203
|
+
guid: (0, crypto_1.randomUUID)(),
|
|
204
|
+
author: currentUser.id,
|
|
205
|
+
name: 'Batch Template 2',
|
|
206
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
207
|
+
descr: 'Second batch template',
|
|
208
|
+
}),
|
|
209
|
+
new FormTemplate_1.FormTemplate({
|
|
210
|
+
id: (0, crypto_1.randomUUID)(),
|
|
211
|
+
guid: (0, crypto_1.randomUUID)(),
|
|
212
|
+
author: currentUser.id,
|
|
213
|
+
name: 'Batch Template 3',
|
|
214
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
215
|
+
descr: 'Third batch template',
|
|
216
|
+
}),
|
|
217
|
+
];
|
|
218
|
+
// Create batch
|
|
219
|
+
const createdTemplates = yield formApi.createFormTemplatesInGroup(groupId, templatesToCreate);
|
|
220
|
+
(0, chai_1.expect)(createdTemplates).to.have.lengthOf(3);
|
|
221
|
+
(0, chai_1.expect)(createdTemplates[0].name).to.equal('Batch Template 1');
|
|
222
|
+
(0, chai_1.expect)(createdTemplates[1].name).to.equal('Batch Template 2');
|
|
223
|
+
(0, chai_1.expect)(createdTemplates[2].name).to.equal('Batch Template 3');
|
|
224
|
+
createdTemplates.forEach((template) => {
|
|
225
|
+
(0, chai_1.expect)(template.id).to.not.be.undefined;
|
|
226
|
+
(0, chai_1.expect)(template.rev).to.not.be.undefined;
|
|
227
|
+
});
|
|
228
|
+
// Get batch by IDs
|
|
229
|
+
const retrievedTemplates = yield formApi.getFormTemplatesInGroup(groupId, createdTemplates.map((t) => t.id));
|
|
230
|
+
(0, chai_1.expect)(retrievedTemplates).to.have.lengthOf(3);
|
|
231
|
+
(0, chai_1.expect)(retrievedTemplates.map((t) => t.id)).to.have.members(createdTemplates.map((t) => t.id));
|
|
232
|
+
// Modify batch
|
|
233
|
+
const templatesForUpdate = createdTemplates.map((t, index) => (Object.assign(Object.assign({}, t), { name: `Updated Batch Template ${index + 1}` })));
|
|
234
|
+
const updatedTemplates = yield formApi.modifyFormTemplatesInGroup(groupId, templatesForUpdate);
|
|
235
|
+
(0, chai_1.expect)(updatedTemplates).to.have.lengthOf(3);
|
|
236
|
+
(0, chai_1.expect)(updatedTemplates[0].name).to.equal('Updated Batch Template 1');
|
|
237
|
+
(0, chai_1.expect)(updatedTemplates[1].name).to.equal('Updated Batch Template 2');
|
|
238
|
+
(0, chai_1.expect)(updatedTemplates[2].name).to.equal('Updated Batch Template 3');
|
|
239
|
+
// Clean up - delete batch
|
|
240
|
+
const idsAndRevs = updatedTemplates.map((t) => new IdWithRev_1.IdWithRev({ id: t.id, rev: t.rev }));
|
|
241
|
+
const deleteResults = yield formApi.deleteFormTemplatesInGroup(groupId, idsAndRevs);
|
|
242
|
+
(0, chai_1.expect)(deleteResults).to.have.lengthOf(3);
|
|
243
|
+
deleteResults.forEach((result) => {
|
|
244
|
+
(0, chai_1.expect)(result.id).to.not.be.undefined;
|
|
245
|
+
(0, chai_1.expect)(result.rev).to.not.be.undefined;
|
|
246
|
+
});
|
|
247
|
+
}));
|
|
248
|
+
it('should delete and undelete multiple form templates in a group (batch)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
249
|
+
// Given
|
|
250
|
+
const { formApi, userApi } = yield initApi(env);
|
|
251
|
+
const currentUser = yield userApi.getCurrentUser();
|
|
252
|
+
const groupId = env.testGroupId;
|
|
253
|
+
const specialtyCode = 'SPECIALTY-' + (0, crypto_1.randomUUID)();
|
|
254
|
+
// Create templates
|
|
255
|
+
const templatesToCreate = [
|
|
256
|
+
new FormTemplate_1.FormTemplate({
|
|
257
|
+
id: (0, crypto_1.randomUUID)(),
|
|
258
|
+
guid: (0, crypto_1.randomUUID)(),
|
|
259
|
+
author: currentUser.id,
|
|
260
|
+
name: 'Delete Test Template 1',
|
|
261
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
262
|
+
}),
|
|
263
|
+
new FormTemplate_1.FormTemplate({
|
|
264
|
+
id: (0, crypto_1.randomUUID)(),
|
|
265
|
+
guid: (0, crypto_1.randomUUID)(),
|
|
266
|
+
author: currentUser.id,
|
|
267
|
+
name: 'Delete Test Template 2',
|
|
268
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
269
|
+
}),
|
|
270
|
+
];
|
|
271
|
+
const createdTemplates = yield formApi.createFormTemplatesInGroup(groupId, templatesToCreate);
|
|
272
|
+
(0, chai_1.expect)(createdTemplates).to.have.lengthOf(2);
|
|
273
|
+
// Delete batch
|
|
274
|
+
const idsAndRevs = createdTemplates.map((t) => new IdWithRev_1.IdWithRev({ id: t.id, rev: t.rev }));
|
|
275
|
+
const deleteResults = yield formApi.deleteFormTemplatesInGroup(groupId, idsAndRevs);
|
|
276
|
+
(0, chai_1.expect)(deleteResults).to.have.lengthOf(2);
|
|
277
|
+
// Verify deletion - templates should not be in active list
|
|
278
|
+
const allTemplates = yield formApi.getFormTemplatesByUserInGroup(groupId, currentUser.id);
|
|
279
|
+
const activeIds = allTemplates.map((t) => t.id);
|
|
280
|
+
createdTemplates.forEach((t) => {
|
|
281
|
+
(0, chai_1.expect)(activeIds).to.not.include(t.id);
|
|
282
|
+
});
|
|
283
|
+
// Undelete batch - use the updated revisions from delete results
|
|
284
|
+
const undeleteIdsAndRevs = deleteResults.map((result) => new IdWithRev_1.IdWithRev({ id: result.id, rev: result.rev }));
|
|
285
|
+
const undeletedTemplates = yield formApi.undeleteFormTemplatesInGroup(groupId, undeleteIdsAndRevs);
|
|
286
|
+
(0, chai_1.expect)(undeletedTemplates).to.have.lengthOf(2);
|
|
287
|
+
undeletedTemplates.forEach((template) => {
|
|
288
|
+
(0, chai_1.expect)(template.id).to.not.be.undefined;
|
|
289
|
+
(0, chai_1.expect)(template.rev).to.not.be.undefined;
|
|
290
|
+
(0, chai_1.expect)(template.deletionDate).to.be.undefined;
|
|
291
|
+
});
|
|
292
|
+
// Verify undelete - templates should be back in active list
|
|
293
|
+
const templatesAfterUndelete = yield formApi.getFormTemplatesByUserInGroup(groupId, currentUser.id);
|
|
294
|
+
const activeIdsAfterUndelete = templatesAfterUndelete.map((t) => t.id);
|
|
295
|
+
undeletedTemplates.forEach((t) => {
|
|
296
|
+
(0, chai_1.expect)(activeIdsAfterUndelete).to.include(t.id);
|
|
297
|
+
});
|
|
298
|
+
// Final cleanup - delete again
|
|
299
|
+
const finalIdsAndRevs = undeletedTemplates.map((t) => new IdWithRev_1.IdWithRev({ id: t.id, rev: t.rev }));
|
|
300
|
+
yield formApi.deleteFormTemplatesInGroup(groupId, finalIdsAndRevs);
|
|
301
|
+
}));
|
|
302
|
+
it('should purge multiple form templates in a group (batch)', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
303
|
+
// Given
|
|
304
|
+
const { formApi, userApi } = yield initApi(env);
|
|
305
|
+
const currentUser = yield userApi.getCurrentUser();
|
|
306
|
+
const groupId = env.testGroupId;
|
|
307
|
+
const specialtyCode = 'SPECIALTY-' + (0, crypto_1.randomUUID)();
|
|
308
|
+
// Create templates
|
|
309
|
+
const templatesToCreate = [
|
|
310
|
+
new FormTemplate_1.FormTemplate({
|
|
311
|
+
id: (0, crypto_1.randomUUID)(),
|
|
312
|
+
guid: (0, crypto_1.randomUUID)(),
|
|
313
|
+
author: currentUser.id,
|
|
314
|
+
name: 'Purge Test Template 1',
|
|
315
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
316
|
+
}),
|
|
317
|
+
new FormTemplate_1.FormTemplate({
|
|
318
|
+
id: (0, crypto_1.randomUUID)(),
|
|
319
|
+
guid: (0, crypto_1.randomUUID)(),
|
|
320
|
+
author: currentUser.id,
|
|
321
|
+
name: 'Purge Test Template 2',
|
|
322
|
+
specialty: new CodeStub_1.CodeStub({ code: specialtyCode, type: 'specialty', version: '1' }),
|
|
323
|
+
}),
|
|
324
|
+
];
|
|
325
|
+
const createdTemplates = yield formApi.createFormTemplatesInGroup(groupId, templatesToCreate);
|
|
326
|
+
(0, chai_1.expect)(createdTemplates).to.have.lengthOf(2);
|
|
327
|
+
// First delete them (purge requires deletion first)
|
|
328
|
+
const deleteIdsAndRevs = createdTemplates.map((t) => new IdWithRev_1.IdWithRev({ id: t.id, rev: t.rev }));
|
|
329
|
+
const deleteResults = yield formApi.deleteFormTemplatesInGroup(groupId, deleteIdsAndRevs);
|
|
330
|
+
(0, chai_1.expect)(deleteResults).to.have.lengthOf(2);
|
|
331
|
+
// Purge batch
|
|
332
|
+
const purgeIdsAndRevs = deleteResults.map((result) => new IdWithRev_1.IdWithRev({ id: result.id, rev: result.rev }));
|
|
333
|
+
const purgeResults = yield formApi.purgeFormTemplatesInGroup(groupId, purgeIdsAndRevs);
|
|
334
|
+
(0, chai_1.expect)(purgeResults).to.have.lengthOf(2);
|
|
335
|
+
purgeResults.forEach((result) => {
|
|
336
|
+
(0, chai_1.expect)(result.id).to.not.be.undefined;
|
|
337
|
+
});
|
|
338
|
+
// Verify purge - trying to get the templates should fail or return empty
|
|
339
|
+
const retrievedTemplates = yield formApi.getFormTemplatesInGroup(groupId, createdTemplates.map((t) => t.id));
|
|
340
|
+
(0, chai_1.expect)(retrievedTemplates).to.have.lengthOf(0);
|
|
341
|
+
}));
|
|
342
|
+
it('should handle empty batch operations gracefully', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
343
|
+
// Given
|
|
344
|
+
const { formApi } = yield initApi(env);
|
|
345
|
+
const groupId = env.testGroupId;
|
|
346
|
+
// Test with empty arrays
|
|
347
|
+
const createdTemplates = yield formApi.createFormTemplatesInGroup(groupId, []);
|
|
348
|
+
(0, chai_1.expect)(createdTemplates).to.have.lengthOf(0);
|
|
349
|
+
const modifiedTemplates = yield formApi.modifyFormTemplatesInGroup(groupId, []);
|
|
350
|
+
(0, chai_1.expect)(modifiedTemplates).to.have.lengthOf(0);
|
|
351
|
+
const retrievedTemplates = yield formApi.getFormTemplatesInGroup(groupId, []);
|
|
352
|
+
(0, chai_1.expect)(retrievedTemplates).to.have.lengthOf(0);
|
|
353
|
+
const deleteResults = yield formApi.deleteFormTemplatesInGroup(groupId, []);
|
|
354
|
+
(0, chai_1.expect)(deleteResults).to.have.lengthOf(0);
|
|
355
|
+
const undeleteResults = yield formApi.undeleteFormTemplatesInGroup(groupId, []);
|
|
356
|
+
(0, chai_1.expect)(undeleteResults).to.have.lengthOf(0);
|
|
357
|
+
const purgeResults = yield formApi.purgeFormTemplatesInGroup(groupId, []);
|
|
358
|
+
(0, chai_1.expect)(purgeResults).to.have.lengthOf(0);
|
|
359
|
+
}));
|
|
360
|
+
});
|
|
97
361
|
});
|
|
98
362
|
//# sourceMappingURL=icc-form-x-api.js.map
|