From 5e81f68564c8e7c6a66a4f83b91b54e76ffbbf3e Mon Sep 17 00:00:00 2001 From: Magnus Kuhn <127854942+Magnus-Kuhn@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:34:33 +0100 Subject: [PATCH] Add UseCases to delete Files, RelationshipTemplates and Tokens (#432) * feat: delete files from backbone * feat: add isOwn check to tokens and templates * feat: adapt files, add use cases * test: add transport tests * refactor: remove unused error * test: add runtime tests * test: fix test * test: improve tests * test: fix token decomposition * fix: sync datawallet * refactor: test names * refactor: capitalize test describe block names Co-authored-by: Britta Stallknecht <146106656+britsta@users.noreply.github.com> * refactor: test name capitalization --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Britta Stallknecht <146106656+britsta@users.noreply.github.com> --- .../facades/transport/FilesFacade.ts | 7 ++ .../transport/RelationshipTemplatesFacade.ts | 7 ++ .../facades/transport/TokensFacade.ts | 7 ++ .../runtime/src/useCases/common/Schemas.ts | 69 +++++++++++++++++++ .../useCases/transport/files/DeleteFile.ts | 37 ++++++++++ .../src/useCases/transport/files/index.ts | 1 + .../DeleteRelationshipTemplate.ts | 37 ++++++++++ .../transport/relationshipTemplates/index.ts | 1 + .../useCases/transport/tokens/DeleteToken.ts | 37 ++++++++++ .../src/useCases/transport/tokens/index.ts | 1 + packages/runtime/test/transport/files.test.ts | 20 ++++++ .../transport/relationshipTemplates.test.ts | 24 +++++++ .../runtime/test/transport/tokens.test.ts | 19 +++++ .../src/modules/files/FileController.ts | 9 +++ .../RelationshipTemplateController.ts | 6 +- .../src/modules/tokens/TokenController.ts | 5 +- .../test/modules/files/FileController.test.ts | 31 +++++++++ .../RelationshipTemplateController.test.ts | 30 ++++++++ .../modules/tokens/TokenController.test.ts | 50 ++++++++++---- 19 files changed, 383 insertions(+), 15 deletions(-) create mode 100644 packages/runtime/src/useCases/transport/files/DeleteFile.ts create mode 100644 packages/runtime/src/useCases/transport/relationshipTemplates/DeleteRelationshipTemplate.ts create mode 100644 packages/runtime/src/useCases/transport/tokens/DeleteToken.ts diff --git a/packages/runtime/src/extensibility/facades/transport/FilesFacade.ts b/packages/runtime/src/extensibility/facades/transport/FilesFacade.ts index ef974d90c..8d6e963b9 100644 --- a/packages/runtime/src/extensibility/facades/transport/FilesFacade.ts +++ b/packages/runtime/src/extensibility/facades/transport/FilesFacade.ts @@ -10,6 +10,8 @@ import { CreateTokenQRCodeForFileRequest, CreateTokenQRCodeForFileResponse, CreateTokenQRCodeForFileUseCase, + DeleteFileRequest, + DeleteFileUseCase, DownloadFileRequest, DownloadFileResponse, DownloadFileUseCase, @@ -30,6 +32,7 @@ export class FilesFacade { @Inject private readonly getFilesUseCase: GetFilesUseCase, @Inject private readonly downloadFileUseCase: DownloadFileUseCase, @Inject private readonly getFileUseCase: GetFileUseCase, + @Inject private readonly deleteFileUseCase: DeleteFileUseCase, @Inject private readonly createQRCodeForFileUseCase: CreateQRCodeForFileUseCase, @Inject private readonly createTokenForFileUseCase: CreateTokenForFileUseCase, @Inject private readonly createTokenQRCodeForFileUseCase: CreateTokenQRCodeForFileUseCase @@ -55,6 +58,10 @@ export class FilesFacade { return await this.uploadOwnFileUseCase.execute(request); } + public async deleteFile(request: DeleteFileRequest): Promise> { + return await this.deleteFileUseCase.execute(request); + } + public async createQRCodeForFile(request: CreateQRCodeForFileRequest): Promise> { return await this.createQRCodeForFileUseCase.execute(request); } diff --git a/packages/runtime/src/extensibility/facades/transport/RelationshipTemplatesFacade.ts b/packages/runtime/src/extensibility/facades/transport/RelationshipTemplatesFacade.ts index 4950e3981..1fddef347 100644 --- a/packages/runtime/src/extensibility/facades/transport/RelationshipTemplatesFacade.ts +++ b/packages/runtime/src/extensibility/facades/transport/RelationshipTemplatesFacade.ts @@ -12,6 +12,8 @@ import { CreateTokenQRCodeForOwnTemplateRequest, CreateTokenQRCodeForOwnTemplateResponse, CreateTokenQRCodeForOwnTemplateUseCase, + DeleteRelationshipTemplateRequest, + DeleteRelationshipTemplateUseCase, GetRelationshipTemplateRequest, GetRelationshipTemplateUseCase, GetRelationshipTemplatesRequest, @@ -26,6 +28,7 @@ export class RelationshipTemplatesFacade { @Inject private readonly loadPeerRelationshipTemplateUseCase: LoadPeerRelationshipTemplateUseCase, @Inject private readonly getRelationshipTemplatesUseCase: GetRelationshipTemplatesUseCase, @Inject private readonly getRelationshipTemplateUseCase: GetRelationshipTemplateUseCase, + @Inject private readonly deleteRelationshipTemplateUseCase: DeleteRelationshipTemplateUseCase, @Inject private readonly createQRCodeForOwnTemplateUseCase: CreateQRCodeForOwnTemplateUseCase, @Inject private readonly createTokenQRCodeForOwnTemplateUseCase: CreateTokenQRCodeForOwnTemplateUseCase, @Inject private readonly createTokenForOwnTemplateUseCase: CreateTokenForOwnTemplateUseCase @@ -47,6 +50,10 @@ export class RelationshipTemplatesFacade { return await this.getRelationshipTemplateUseCase.execute(request); } + public async deleteRelationshipTemplate(request: DeleteRelationshipTemplateRequest): Promise> { + return await this.deleteRelationshipTemplateUseCase.execute(request); + } + public async createQRCodeForOwnTemplate(request: CreateQRCodeForOwnTemplateRequest): Promise> { return await this.createQRCodeForOwnTemplateUseCase.execute(request); } diff --git a/packages/runtime/src/extensibility/facades/transport/TokensFacade.ts b/packages/runtime/src/extensibility/facades/transport/TokensFacade.ts index 4c4969438..7f038cc0e 100644 --- a/packages/runtime/src/extensibility/facades/transport/TokensFacade.ts +++ b/packages/runtime/src/extensibility/facades/transport/TokensFacade.ts @@ -4,6 +4,8 @@ import { TokenDTO } from "../../../types"; import { CreateOwnTokenRequest, CreateOwnTokenUseCase, + DeleteTokenRequest, + DeleteTokenUseCase, GetQRCodeForTokenRequest, GetQRCodeForTokenResponse, GetQRCodeForTokenUseCase, @@ -21,6 +23,7 @@ export class TokensFacade { @Inject private readonly loadPeerTokenUseCase: LoadPeerTokenUseCase, @Inject private readonly getTokensUseCase: GetTokensUseCase, @Inject private readonly getTokenUseCase: GetTokenUseCase, + @Inject private readonly deleteTokenUseCase: DeleteTokenUseCase, @Inject private readonly getQRCodeForTokenUseCase: GetQRCodeForTokenUseCase ) {} @@ -40,6 +43,10 @@ export class TokensFacade { return await this.getTokenUseCase.execute(request); } + public async deleteToken(request: DeleteTokenRequest): Promise> { + return await this.deleteTokenUseCase.execute(request); + } + public async getQRCodeForToken(request: GetQRCodeForTokenRequest): Promise> { return await this.getQRCodeForTokenUseCase.execute(request); } diff --git a/packages/runtime/src/useCases/common/Schemas.ts b/packages/runtime/src/useCases/common/Schemas.ts index 9d4825f1e..517e22dea 100644 --- a/packages/runtime/src/useCases/common/Schemas.ts +++ b/packages/runtime/src/useCases/common/Schemas.ts @@ -20284,6 +20284,29 @@ export const CreateTokenQRCodeForFileRequest: any = { } } +export const DeleteFileRequest: any = { + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/DeleteFileRequest", + "definitions": { + "DeleteFileRequest": { + "type": "object", + "properties": { + "fileId": { + "$ref": "#/definitions/FileIdString" + } + }, + "required": [ + "fileId" + ], + "additionalProperties": false + }, + "FileIdString": { + "type": "string", + "pattern": "FIL[A-Za-z0-9]{17}" + } + } +} + export const GetFileRequest: any = { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/GetFileRequest", @@ -21574,6 +21597,29 @@ export const CreateTokenQRCodeForOwnTemplateRequest: any = { } } +export const DeleteRelationshipTemplateRequest: any = { + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/DeleteRelationshipTemplateRequest", + "definitions": { + "DeleteRelationshipTemplateRequest": { + "type": "object", + "properties": { + "templateId": { + "$ref": "#/definitions/RelationshipTemplateIdString" + } + }, + "required": [ + "templateId" + ], + "additionalProperties": false + }, + "RelationshipTemplateIdString": { + "type": "string", + "pattern": "RLT[A-Za-z0-9]{17}" + } + } +} + export const GetRelationshipTemplateRequest: any = { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/GetRelationshipTemplateRequest", @@ -21839,6 +21885,29 @@ export const CreateOwnTokenRequest: any = { } } +export const DeleteTokenRequest: any = { + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/DeleteTokenRequest", + "definitions": { + "DeleteTokenRequest": { + "type": "object", + "properties": { + "tokenId": { + "$ref": "#/definitions/TokenIdString" + } + }, + "required": [ + "tokenId" + ], + "additionalProperties": false + }, + "TokenIdString": { + "type": "string", + "pattern": "TOK[A-Za-z0-9]{17}" + } + } +} + export const GetQRCodeForTokenRequest: any = { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/GetQRCodeForTokenRequest", diff --git a/packages/runtime/src/useCases/transport/files/DeleteFile.ts b/packages/runtime/src/useCases/transport/files/DeleteFile.ts new file mode 100644 index 000000000..6bb6bd608 --- /dev/null +++ b/packages/runtime/src/useCases/transport/files/DeleteFile.ts @@ -0,0 +1,37 @@ +import { Result } from "@js-soft/ts-utils"; +import { CoreId } from "@nmshd/core-types"; +import { AccountController, File, FileController } from "@nmshd/transport"; +import { Inject } from "@nmshd/typescript-ioc"; +import { FileIdString, RuntimeErrors, SchemaRepository, SchemaValidator, UseCase } from "../../common"; + +export interface DeleteFileRequest { + fileId: FileIdString; +} + +class Validator extends SchemaValidator { + public constructor(@Inject schemaRepository: SchemaRepository) { + super(schemaRepository.getSchema("DeleteFileRequest")); + } +} + +export class DeleteFileUseCase extends UseCase { + public constructor( + @Inject private readonly fileController: FileController, + @Inject private readonly accountController: AccountController, + @Inject validator: Validator + ) { + super(validator); + } + + protected async executeInternal(request: DeleteFileRequest): Promise> { + const file = await this.fileController.getFile(CoreId.from(request.fileId)); + if (!file) { + return Result.fail(RuntimeErrors.general.recordNotFound(File)); + } + + await this.fileController.deleteFile(file); + await this.accountController.syncDatawallet(); + + return Result.ok(undefined); + } +} diff --git a/packages/runtime/src/useCases/transport/files/index.ts b/packages/runtime/src/useCases/transport/files/index.ts index dec53b506..c62ca17bd 100644 --- a/packages/runtime/src/useCases/transport/files/index.ts +++ b/packages/runtime/src/useCases/transport/files/index.ts @@ -1,6 +1,7 @@ export * from "./CreateQRCodeForFile"; export * from "./CreateTokenForFile"; export * from "./CreateTokenQRCodeForFile"; +export * from "./DeleteFile"; export * from "./DownloadFile"; export * from "./FileMapper"; export * from "./GetFile"; diff --git a/packages/runtime/src/useCases/transport/relationshipTemplates/DeleteRelationshipTemplate.ts b/packages/runtime/src/useCases/transport/relationshipTemplates/DeleteRelationshipTemplate.ts new file mode 100644 index 000000000..8ce9b84c5 --- /dev/null +++ b/packages/runtime/src/useCases/transport/relationshipTemplates/DeleteRelationshipTemplate.ts @@ -0,0 +1,37 @@ +import { Result } from "@js-soft/ts-utils"; +import { CoreId } from "@nmshd/core-types"; +import { AccountController, RelationshipTemplate, RelationshipTemplateController } from "@nmshd/transport"; +import { Inject } from "@nmshd/typescript-ioc"; +import { RelationshipTemplateIdString, RuntimeErrors, SchemaRepository, SchemaValidator, UseCase } from "../../common"; + +export interface DeleteRelationshipTemplateRequest { + templateId: RelationshipTemplateIdString; +} + +class Validator extends SchemaValidator { + public constructor(@Inject schemaRepository: SchemaRepository) { + super(schemaRepository.getSchema("DeleteRelationshipTemplateRequest")); + } +} + +export class DeleteRelationshipTemplateUseCase extends UseCase { + public constructor( + @Inject private readonly relationshipTemplateController: RelationshipTemplateController, + @Inject private readonly accountController: AccountController, + @Inject validator: Validator + ) { + super(validator); + } + + protected async executeInternal(request: DeleteRelationshipTemplateRequest): Promise> { + const template = await this.relationshipTemplateController.getRelationshipTemplate(CoreId.from(request.templateId)); + if (!template) { + return Result.fail(RuntimeErrors.general.recordNotFound(RelationshipTemplate)); + } + + await this.relationshipTemplateController.deleteRelationshipTemplate(template); + await this.accountController.syncDatawallet(); + + return Result.ok(undefined); + } +} diff --git a/packages/runtime/src/useCases/transport/relationshipTemplates/index.ts b/packages/runtime/src/useCases/transport/relationshipTemplates/index.ts index d16294a37..327d4f86b 100644 --- a/packages/runtime/src/useCases/transport/relationshipTemplates/index.ts +++ b/packages/runtime/src/useCases/transport/relationshipTemplates/index.ts @@ -2,6 +2,7 @@ export * from "./CreateOwnRelationshipTemplate"; export * from "./CreateQRCodeForOwnRelationshipTemplate"; export * from "./CreateTokenForOwnRelationshipTemplate"; export * from "./CreateTokenQRCodeForOwnRelationshipTemplate"; +export * from "./DeleteRelationshipTemplate"; export * from "./GetRelationshipTemplate"; export * from "./GetRelationshipTemplates"; export * from "./LoadPeerRelationshipTemplate"; diff --git a/packages/runtime/src/useCases/transport/tokens/DeleteToken.ts b/packages/runtime/src/useCases/transport/tokens/DeleteToken.ts new file mode 100644 index 000000000..17c5f668d --- /dev/null +++ b/packages/runtime/src/useCases/transport/tokens/DeleteToken.ts @@ -0,0 +1,37 @@ +import { Result } from "@js-soft/ts-utils"; +import { CoreId } from "@nmshd/core-types"; +import { AccountController, Token, TokenController } from "@nmshd/transport"; +import { Inject } from "@nmshd/typescript-ioc"; +import { RuntimeErrors, SchemaRepository, SchemaValidator, TokenIdString, UseCase } from "../../common"; + +export interface DeleteTokenRequest { + tokenId: TokenIdString; +} + +class Validator extends SchemaValidator { + public constructor(@Inject schemaRepository: SchemaRepository) { + super(schemaRepository.getSchema("DeleteTokenRequest")); + } +} + +export class DeleteTokenUseCase extends UseCase { + public constructor( + @Inject private readonly tokenController: TokenController, + @Inject private readonly accountController: AccountController, + @Inject validator: Validator + ) { + super(validator); + } + + protected async executeInternal(request: DeleteTokenRequest): Promise> { + const token = await this.tokenController.getToken(CoreId.from(request.tokenId)); + if (!token) { + return Result.fail(RuntimeErrors.general.recordNotFound(Token)); + } + + await this.tokenController.delete(token); + await this.accountController.syncDatawallet(); + + return Result.ok(undefined); + } +} diff --git a/packages/runtime/src/useCases/transport/tokens/index.ts b/packages/runtime/src/useCases/transport/tokens/index.ts index 9bc2fa8b2..e24677619 100644 --- a/packages/runtime/src/useCases/transport/tokens/index.ts +++ b/packages/runtime/src/useCases/transport/tokens/index.ts @@ -1,4 +1,5 @@ export * from "./CreateOwnToken"; +export * from "./DeleteToken"; export * from "./GetQRCodeForToken"; export * from "./GetToken"; export * from "./GetTokens"; diff --git a/packages/runtime/test/transport/files.test.ts b/packages/runtime/test/transport/files.test.ts index 769d19566..af7d33d59 100644 --- a/packages/runtime/test/transport/files.test.ts +++ b/packages/runtime/test/transport/files.test.ts @@ -197,6 +197,26 @@ describe("Upload big files", () => { }); }); +describe("Delete file", () => { + test("accessing invalid file id causes an error", async () => { + const response = await transportServices1.files.deleteFile({ fileId: UNKNOWN_FILE_ID }); + expect(response).toBeAnError("File not found. Make sure the ID exists and the record is not expired.", "error.runtime.recordNotFound"); + }); + + test("successfully delete file", async () => { + const uploadResponse = await transportServices1.files.uploadOwnFile(await makeUploadRequest()); + expect(uploadResponse).toBeSuccessful(); + const file = uploadResponse.value; + expect(file).toBeDefined(); + + const deleteFileResponse = await transportServices1.files.deleteFile({ fileId: file.id }); + expect(deleteFileResponse).toBeSuccessful(); + + const getFileResponse = await transportServices1.files.getFile({ id: file.id }); + expect(getFileResponse).toBeAnError("File not found. Make sure the ID exists and the record is not expired.", "error.runtime.recordNotFound"); + }); +}); + describe("Files query", () => { test("files can be queried by their attributes", async () => { const file = await uploadFile(transportServices1); diff --git a/packages/runtime/test/transport/relationshipTemplates.test.ts b/packages/runtime/test/transport/relationshipTemplates.test.ts index b89ed1d8e..551f9a13a 100644 --- a/packages/runtime/test/transport/relationshipTemplates.test.ts +++ b/packages/runtime/test/transport/relationshipTemplates.test.ts @@ -7,6 +7,8 @@ const serviceProvider = new RuntimeServiceProvider(); let runtimeServices1: TestRuntimeServices; let runtimeServices2: TestRuntimeServices; +const UNKNOWN_TEMPLATE_ID = "RLTXXXXXXXXXXXXXXXXX"; + beforeAll(async () => { const runtimeServices = await serviceProvider.launch(2); runtimeServices1 = runtimeServices[0]; @@ -247,6 +249,28 @@ describe("RelationshipTemplate Tests", () => { expect(createQRCodeWithoutPersonalizationResult).toBeAnError(/.*/, "error.runtime.relationshipTemplates.personalizationMustBeInherited"); }); }); + + describe("Delete template", () => { + test("accessing invalid template id causes an error", async () => { + const response = await runtimeServices1.transport.relationshipTemplates.deleteRelationshipTemplate({ templateId: UNKNOWN_TEMPLATE_ID }); + expect(response).toBeAnError("RelationshipTemplate not found. Make sure the ID exists and the record is not expired.", "error.runtime.recordNotFound"); + }); + + test("successfully delete template", async () => { + const template = ( + await runtimeServices1.transport.relationshipTemplates.createOwnRelationshipTemplate({ + content: emptyRelationshipTemplateContent, + expiresAt: DateTime.utc().plus({ minutes: 1 }).toString() + }) + ).value; + + const deleteTemplateResponse = await runtimeServices1.transport.relationshipTemplates.deleteRelationshipTemplate({ templateId: template.id }); + expect(deleteTemplateResponse).toBeSuccessful(); + + const getTemplateResponse = await runtimeServices1.transport.relationshipTemplates.getRelationshipTemplate({ id: template.id }); + expect(getTemplateResponse).toBeAnError("RelationshipTemplate not found. Make sure the ID exists and the record is not expired.", "error.runtime.recordNotFound"); + }); + }); }); describe("Serialization Errors", () => { diff --git a/packages/runtime/test/transport/tokens.test.ts b/packages/runtime/test/transport/tokens.test.ts index 482b7f4ce..7d965064a 100644 --- a/packages/runtime/test/transport/tokens.test.ts +++ b/packages/runtime/test/transport/tokens.test.ts @@ -6,6 +6,8 @@ const serviceProvider = new RuntimeServiceProvider(); let runtimeServices1: TestRuntimeServices; let runtimeServices2: TestRuntimeServices; +const UNKNOWN_TOKEN_ID = "TOKXXXXXXXXXXXXXXXXX"; + beforeAll(async () => { const runtimeServices = await serviceProvider.launch(2); runtimeServices1 = runtimeServices[0]; @@ -34,6 +36,23 @@ describe("Tokens", () => { const getTokenResponse = await runtimeServices1.transport.tokens.getToken({ id: response.value.id }); expect(getTokenResponse).toBeAnError("Token not found. Make sure the ID exists and the record is not expired.", "error.runtime.recordNotFound"); }); + + describe("Delete Token", () => { + test("accessing invalid Token id causes an error", async () => { + const response = await runtimeServices1.transport.tokens.deleteToken({ tokenId: UNKNOWN_TOKEN_ID }); + expect(response).toBeAnError("Token not found. Make sure the ID exists and the record is not expired.", "error.runtime.recordNotFound"); + }); + + test("successfully delete Token", async () => { + const token = await uploadOwnToken(runtimeServices1.transport); + + const deleteTokenResponse = await runtimeServices1.transport.tokens.deleteToken({ tokenId: token.id }); + expect(deleteTokenResponse).toBeSuccessful(); + + const getTokenResponse = await runtimeServices1.transport.tokens.getToken({ id: token.id }); + expect(getTokenResponse).toBeAnError("Token not found. Make sure the ID exists and the record is not expired.", "error.runtime.recordNotFound"); + }); + }); }); describe("Tokens errors", () => { diff --git a/packages/transport/src/modules/files/FileController.ts b/packages/transport/src/modules/files/FileController.ts index 394858ae0..f21fd52c3 100644 --- a/packages/transport/src/modules/files/FileController.ts +++ b/packages/transport/src/modules/files/FileController.ts @@ -42,6 +42,15 @@ export class FileController extends TransportController { return doc ? File.from(doc) : undefined; } + public async deleteFile(file: File): Promise { + if (file.isOwn) { + const response = await this.client.deleteFile(file.id.toString()); + if (response.isError) throw response.error; + } + + await this.files.delete(file); + } + public async fetchCaches(ids: CoreId[]): Promise<{ id: CoreId; cache: CachedFile }[]> { if (ids.length === 0) return []; diff --git a/packages/transport/src/modules/relationshipTemplates/RelationshipTemplateController.ts b/packages/transport/src/modules/relationshipTemplates/RelationshipTemplateController.ts index 84f82db79..4b9734452 100644 --- a/packages/transport/src/modules/relationshipTemplates/RelationshipTemplateController.ts +++ b/packages/transport/src/modules/relationshipTemplates/RelationshipTemplateController.ts @@ -112,8 +112,10 @@ export class RelationshipTemplateController extends TransportController { } public async deleteRelationshipTemplate(template: RelationshipTemplate): Promise { - const response = await this.client.deleteRelationshipTemplate(template.id.toString()); - if (response.isError) throw response.error; + if (template.isOwn) { + const response = await this.client.deleteRelationshipTemplate(template.id.toString()); + if (response.isError) throw response.error; + } await this.templates.delete(template); } diff --git a/packages/transport/src/modules/tokens/TokenController.ts b/packages/transport/src/modules/tokens/TokenController.ts index 051885d63..770a9ea33 100644 --- a/packages/transport/src/modules/tokens/TokenController.ts +++ b/packages/transport/src/modules/tokens/TokenController.ts @@ -296,7 +296,10 @@ export class TokenController extends TransportController { } public async delete(token: Token): Promise { - if (token.isOwn) await this.client.deleteToken(token.id.toString()); + if (token.isOwn) { + const response = await this.client.deleteToken(token.id.toString()); + if (response.isError) throw response.error; + } await this.tokens.delete(token); } diff --git a/packages/transport/test/modules/files/FileController.test.ts b/packages/transport/test/modules/files/FileController.test.ts index a49fe0506..956f6266d 100644 --- a/packages/transport/test/modules/files/FileController.test.ts +++ b/packages/transport/test/modules/files/FileController.test.ts @@ -123,4 +123,35 @@ describe("FileController", function () { expect(file.metadataModifiedAt!.isSameOrBefore(creationTime.add({ seconds: 1 }))).toBe(true); expect(file.metadataModifiedAt!.isSameOrAfter(creationTime.subtract({ seconds: 2 }))).toBe(true); }); + + describe("File deletion", function () { + let sentFile: File; + let receivedFile: File; + + beforeEach(async function () { + const content = CoreBuffer.fromUtf8("Test"); + sentFile = await TestUtil.uploadFile(sender, content); + + const reference = sentFile.toFileReference().truncate(); + receivedFile = await recipient.files.getOrLoadFileByTruncated(reference); + }); + + test("should delete own file locally and from the backbone", async function () { + await sender.files.deleteFile(sentFile); + const fileOnBackbone = await recipient.files.fetchCaches([sentFile.id]); + expect(fileOnBackbone).toHaveLength(0); + + const localFile = await sender.files.getFile(sentFile.id); + expect(localFile).toBeUndefined(); + }); + + test("should delete a peer owned file only locally", async function () { + await recipient.files.deleteFile(receivedFile); + const fileOnBackbone = await sender.files.fetchCaches([sentFile.id]); + expect(fileOnBackbone).toHaveLength(1); + + const localFile = await recipient.files.getFile(sentFile.id); + expect(localFile).toBeUndefined(); + }); + }); }); diff --git a/packages/transport/test/modules/relationshipTemplates/RelationshipTemplateController.test.ts b/packages/transport/test/modules/relationshipTemplates/RelationshipTemplateController.test.ts index 1bf019b38..5e6f68ecc 100644 --- a/packages/transport/test/modules/relationshipTemplates/RelationshipTemplateController.test.ts +++ b/packages/transport/test/modules/relationshipTemplates/RelationshipTemplateController.test.ts @@ -248,4 +248,34 @@ describe("RelationshipTemplateController", function () { expect(templateForRelationship).toBeUndefined(); expect(otherTemplate).toBeUndefined(); }); + + describe("RelationshipTemplate deletion", function () { + let ownTemplate: RelationshipTemplate; + let peerTemplate: RelationshipTemplate; + + beforeEach(async function () { + ownTemplate = await TestUtil.sendRelationshipTemplate(sender); + + const reference = ownTemplate.toRelationshipTemplateReference().truncate(); + peerTemplate = await recipient.relationshipTemplates.loadPeerRelationshipTemplateByTruncated(reference); + }); + + test("should delete own RelationshipTemplate locally and from the backbone", async function () { + await sender.relationshipTemplates.deleteRelationshipTemplate(ownTemplate); + const templateOnBackbone = await recipient.relationshipTemplates.fetchCaches([ownTemplate.id]); + expect(templateOnBackbone).toHaveLength(0); + + const localTemplate = await sender.relationshipTemplates.getRelationshipTemplate(ownTemplate.id); + expect(localTemplate).toBeUndefined(); + }); + + test("should delete a peer owned RelationshipTemplate only locally", async function () { + await recipient.relationshipTemplates.deleteRelationshipTemplate(peerTemplate); + const templateOnBackbone = await sender.relationshipTemplates.fetchCaches([ownTemplate.id]); + expect(templateOnBackbone).toHaveLength(1); + + const localTemplate = await recipient.relationshipTemplates.getRelationshipTemplate(ownTemplate.id); + expect(localTemplate).toBeUndefined(); + }); + }); }); diff --git a/packages/transport/test/modules/tokens/TokenController.test.ts b/packages/transport/test/modules/tokens/TokenController.test.ts index 12099f356..f6931f325 100644 --- a/packages/transport/test/modules/tokens/TokenController.test.ts +++ b/packages/transport/test/modules/tokens/TokenController.test.ts @@ -396,19 +396,45 @@ describe("TokenController", function () { expect(fetchCachesResult).toHaveLength(2); }); - test("should delete a token", async function () { - const expiresAt = CoreDate.utc().add({ minutes: 5 }); - const content = Serializable.fromAny({ content: "TestToken" }); - const sentToken = await recipient.tokens.sendToken({ - content, - expiresAt, - ephemeral: false + describe("Token deletion", function () { + let sentToken: Token; + let receivedToken: Token; + + beforeEach(async function () { + const expiresAt = CoreDate.utc().add({ minutes: 5 }); + const content = Serializable.fromAny({ content: "TestToken" }); + sentToken = await sender.tokens.sendToken({ + content, + expiresAt, + ephemeral: false + }); + + const reference = sentToken.toTokenReference().truncate(); + receivedToken = await recipient.tokens.loadPeerTokenByTruncated(reference, false); }); - const reference = sentToken.toTokenReference().truncate(); - const tokenId = (await sender.tokens.loadPeerTokenByTruncated(reference, false)).id; - await sender.tokens.cleanupTokensOfDecomposedRelationship(recipient.identity.address); - const token = await sender.tokens.getToken(tokenId); - expect(token).toBeUndefined(); + test("should delete own token locally and from the backbone", async function () { + await sender.tokens.delete(sentToken); + const tokenOnBackbone = await recipient.tokens.fetchCaches([sentToken.id]); + expect(tokenOnBackbone).toHaveLength(0); + + const localToken = await sender.tokens.getToken(sentToken.id); + expect(localToken).toBeUndefined(); + }); + + test("should delete a peer owned token only locally", async function () { + await recipient.tokens.delete(receivedToken); + const tokenOnBackbone = await sender.tokens.fetchCaches([sentToken.id]); + expect(tokenOnBackbone).toHaveLength(1); + + const localToken = await recipient.tokens.getToken(sentToken.id); + expect(localToken).toBeUndefined(); + }); + + test("should delete a token during decomposition", async function () { + await recipient.tokens.cleanupTokensOfDecomposedRelationship(sender.identity.address); + const token = await recipient.tokens.getToken(sentToken.id); + expect(token).toBeUndefined(); + }); }); });