From 583b8a08529cef67b7ec5fca1f6198a06a3d3842 Mon Sep 17 00:00:00 2001 From: Arne Gnisa Date: Mon, 17 Jun 2024 18:21:42 +0200 Subject: [PATCH] N21-1967 fix amqp filestorage (#5066) * fixes copying of files --- .../infra/rabbitmq/exchange/files-storage.ts | 4 +++- .../internal/board-node-copy-context.spec.ts | 13 +++++++---- .../internal/board-node-copy-context.ts | 13 +++++++---- .../board-node-copy-general.service.spec.ts | 7 ++++-- .../board-node-copy-specific.service.spec.ts | 7 ++++-- .../internal/column-board-copy.service.ts | 11 +++++---- .../interfaces/file-request-info.ts | 4 +++- ...copy-files-of-parent-param.builder.spec.ts | 23 +++++++++++-------- .../files-storage-param.builder.spec.ts | 14 ++++++----- .../mapper/files-storage-param.builder.ts | 10 ++++++-- .../service/copy-files.service.ts | 5 ++-- .../files-storage-client.service.spec.ts | 9 ++++---- .../service/files-storage.producer.spec.ts | 15 ++++++++---- 13 files changed, 89 insertions(+), 46 deletions(-) diff --git a/apps/server/src/infra/rabbitmq/exchange/files-storage.ts b/apps/server/src/infra/rabbitmq/exchange/files-storage.ts index 75adc45193a..68acac4e0e4 100644 --- a/apps/server/src/infra/rabbitmq/exchange/files-storage.ts +++ b/apps/server/src/infra/rabbitmq/exchange/files-storage.ts @@ -1,3 +1,4 @@ +import { StorageLocation } from '@modules/files-storage/entity'; import { EntityId } from '@shared/domain/types'; export enum FilesStorageEvents { @@ -35,7 +36,8 @@ export interface CopyFilesOfParentParams { } export interface FileRecordParams { - schoolId: EntityId; + storageLocationId: EntityId; + storageLocation: StorageLocation; parentId: EntityId; parentType: FileRecordParentType; } diff --git a/apps/server/src/modules/board/service/internal/board-node-copy-context.spec.ts b/apps/server/src/modules/board/service/internal/board-node-copy-context.spec.ts index 410e8d818ea..c25a2dbe3c8 100644 --- a/apps/server/src/modules/board/service/internal/board-node-copy-context.spec.ts +++ b/apps/server/src/modules/board/service/internal/board-node-copy-context.spec.ts @@ -1,5 +1,6 @@ import { createMock } from '@golevelup/ts-jest'; import { ObjectId } from '@mikro-orm/mongodb'; +import { StorageLocation } from '@modules/files-storage/entity'; import { FileRecordParentType } from '@src/infra/rabbitmq'; import { FilesStorageClientAdapterService } from '@src/modules/files-storage-client'; import { BoardNodeCopyContext } from './board-node-copy-context'; @@ -8,8 +9,10 @@ describe(BoardNodeCopyContext.name, () => { describe('copyFilesOfParent', () => { const setup = () => { const contextProps = { - sourceSchoolId: new ObjectId().toHexString(), - targetSchoolId: new ObjectId().toHexString(), + sourceStorageLocationId: new ObjectId().toHexString(), + targetStorageLocationId: new ObjectId().toHexString(), + sourceStorageLocation: StorageLocation.SCHOOL, + targetStorageLocation: StorageLocation.SCHOOL, userId: new ObjectId().toHexString(), filesStorageClientAdapterService: createMock(), }; @@ -31,12 +34,14 @@ describe(BoardNodeCopyContext.name, () => { source: { parentId: sourceParentId, parentType: FileRecordParentType.BoardNode, - schoolId: contextProps.sourceSchoolId, + storageLocationId: contextProps.sourceStorageLocationId, + storageLocation: contextProps.sourceStorageLocation, }, target: { parentId: targetParentId, parentType: FileRecordParentType.BoardNode, - schoolId: contextProps.targetSchoolId, + storageLocationId: contextProps.targetStorageLocationId, + storageLocation: contextProps.targetStorageLocation, }, userId: contextProps.userId, }); diff --git a/apps/server/src/modules/board/service/internal/board-node-copy-context.ts b/apps/server/src/modules/board/service/internal/board-node-copy-context.ts index f32c148ad55..b073b978e59 100644 --- a/apps/server/src/modules/board/service/internal/board-node-copy-context.ts +++ b/apps/server/src/modules/board/service/internal/board-node-copy-context.ts @@ -1,13 +1,16 @@ import { FilesStorageClientAdapterService } from '@modules/files-storage-client'; import { CopyFileDto } from '@modules/files-storage-client/dto'; +import { StorageLocation } from '@modules/files-storage/entity'; import { EntityId } from '@shared/domain/types'; import { FileRecordParentType } from '@src/infra/rabbitmq'; import { CopyContext } from './board-node-copy.service'; export type BoardNodeCopyContextProps = { - sourceSchoolId: EntityId; - targetSchoolId: EntityId; + sourceStorageLocationId: EntityId; + targetStorageLocationId: EntityId; userId: EntityId; + sourceStorageLocation: StorageLocation; + targetStorageLocation: StorageLocation; filesStorageClientAdapterService: FilesStorageClientAdapterService; }; @@ -19,12 +22,14 @@ export class BoardNodeCopyContext implements CopyContext { source: { parentId: sourceParentId, parentType: FileRecordParentType.BoardNode, - schoolId: this.props.sourceSchoolId, + storageLocationId: this.props.sourceStorageLocationId, + storageLocation: this.props.sourceStorageLocation, }, target: { parentId: targetParentId, parentType: FileRecordParentType.BoardNode, - schoolId: this.props.targetSchoolId, + storageLocationId: this.props.targetStorageLocationId, + storageLocation: this.props.targetStorageLocation, }, userId: this.props.userId, }); diff --git a/apps/server/src/modules/board/service/internal/board-node-copy-general.service.spec.ts b/apps/server/src/modules/board/service/internal/board-node-copy-general.service.spec.ts index 2ae327b906d..7402a8c1436 100644 --- a/apps/server/src/modules/board/service/internal/board-node-copy-general.service.spec.ts +++ b/apps/server/src/modules/board/service/internal/board-node-copy-general.service.spec.ts @@ -1,6 +1,7 @@ import { createMock } from '@golevelup/ts-jest'; import { ObjectId } from '@mikro-orm/mongodb'; import { CopyElementType, CopyHelperService, CopyStatus, CopyStatusEnum } from '@modules/copy-helper'; +import { StorageLocation } from '@modules/files-storage/entity'; import { ContextExternalToolService } from '@modules/tool/context-external-tool/service'; import { IToolFeatures, ToolFeatures } from '@modules/tool/tool-config'; import { Test, TestingModule } from '@nestjs/testing'; @@ -63,8 +64,10 @@ describe(BoardNodeCopyService.name, () => { const setup = () => { const contextProps: BoardNodeCopyContextProps = { - sourceSchoolId: new ObjectId().toHexString(), - targetSchoolId: new ObjectId().toHexString(), + sourceStorageLocationId: new ObjectId().toHexString(), + sourceStorageLocation: StorageLocation.SCHOOL, + targetStorageLocationId: new ObjectId().toHexString(), + targetStorageLocation: StorageLocation.SCHOOL, userId: new ObjectId().toHexString(), filesStorageClientAdapterService: createMock(), }; diff --git a/apps/server/src/modules/board/service/internal/board-node-copy-specific.service.spec.ts b/apps/server/src/modules/board/service/internal/board-node-copy-specific.service.spec.ts index 5a61350fb8c..99299317481 100644 --- a/apps/server/src/modules/board/service/internal/board-node-copy-specific.service.spec.ts +++ b/apps/server/src/modules/board/service/internal/board-node-copy-specific.service.spec.ts @@ -1,6 +1,7 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { ObjectId } from '@mikro-orm/mongodb'; import { CopyElementType, CopyHelperService, CopyStatus, CopyStatusEnum } from '@modules/copy-helper'; +import { StorageLocation } from '@modules/files-storage/entity'; import { ContextExternalToolService } from '@modules/tool/context-external-tool/service'; import { IToolFeatures, ToolFeatures } from '@modules/tool/tool-config'; import { Test, TestingModule } from '@nestjs/testing'; @@ -89,8 +90,10 @@ describe(BoardNodeCopyService.name, () => { const setupContext = () => { const contextProps = { - sourceSchoolId: new ObjectId().toHexString(), - targetSchoolId: new ObjectId().toHexString(), + sourceStorageLocationId: new ObjectId().toHexString(), + sourceStorageLocation: StorageLocation.SCHOOL, + targetStorageLocationId: new ObjectId().toHexString(), + targetStorageLocation: StorageLocation.SCHOOL, userId: new ObjectId().toHexString(), filesStorageClientAdapterService: createMock(), }; diff --git a/apps/server/src/modules/board/service/internal/column-board-copy.service.ts b/apps/server/src/modules/board/service/internal/column-board-copy.service.ts index 6ebe47bd942..4ea92ccccd5 100644 --- a/apps/server/src/modules/board/service/internal/column-board-copy.service.ts +++ b/apps/server/src/modules/board/service/internal/column-board-copy.service.ts @@ -1,13 +1,14 @@ import { CopyStatus } from '@modules/copy-helper'; +import { FilesStorageClientAdapterService } from '@modules/files-storage-client'; +import { StorageLocation } from '@modules/files-storage/entity'; import { UserService } from '@modules/user'; import { Injectable, InternalServerErrorException, NotImplementedException } from '@nestjs/common'; import { EntityId } from '@shared/domain/types'; import { CourseRepo } from '@shared/repo'; -import { FilesStorageClientAdapterService } from '@modules/files-storage-client'; import { BoardExternalReference, BoardExternalReferenceType, ColumnBoard, isColumnBoard } from '../../domain'; +import { BoardNodeService } from '../board-node.service'; import { BoardNodeCopyContext } from './board-node-copy-context'; import { BoardNodeCopyService } from './board-node-copy.service'; -import { BoardNodeService } from '../board-node.service'; import { ColumnBoardTitleService } from './column-board-title.service'; @Injectable() @@ -37,8 +38,10 @@ export class ColumnBoardCopyService { const course = await this.courseRepo.findById(originalBoard.context.id); // TODO: get rid of this const copyContext = new BoardNodeCopyContext({ - sourceSchoolId: course.school.id, - targetSchoolId: user.schoolId, + sourceStorageLocationId: course.school.id, + targetStorageLocationId: user.schoolId, + sourceStorageLocation: StorageLocation.SCHOOL, + targetStorageLocation: StorageLocation.SCHOOL, userId: props.userId, filesStorageClientAdapterService: this.filesStorageClientAdapterService, }); diff --git a/apps/server/src/modules/files-storage-client/interfaces/file-request-info.ts b/apps/server/src/modules/files-storage-client/interfaces/file-request-info.ts index 76b41b396b5..9970544983e 100644 --- a/apps/server/src/modules/files-storage-client/interfaces/file-request-info.ts +++ b/apps/server/src/modules/files-storage-client/interfaces/file-request-info.ts @@ -1,8 +1,10 @@ import { FileRecordParentType } from '@infra/rabbitmq'; +import { StorageLocation } from '@modules/files-storage/entity'; import { EntityId } from '@shared/domain/types'; export interface FileRequestInfo { - schoolId: EntityId; + storageLocationId: EntityId; + storageLocation: StorageLocation; parentType: FileRecordParentType; parentId: EntityId; } diff --git a/apps/server/src/modules/files-storage-client/mapper/copy-files-of-parent-param.builder.spec.ts b/apps/server/src/modules/files-storage-client/mapper/copy-files-of-parent-param.builder.spec.ts index ccce67a089a..352ace95fc5 100644 --- a/apps/server/src/modules/files-storage-client/mapper/copy-files-of-parent-param.builder.spec.ts +++ b/apps/server/src/modules/files-storage-client/mapper/copy-files-of-parent-param.builder.spec.ts @@ -1,5 +1,6 @@ -import { ObjectId } from '@mikro-orm/mongodb'; import { FileRecordParentType } from '@infra/rabbitmq'; +import { ObjectId } from '@mikro-orm/mongodb'; +import { StorageLocation } from '@modules/files-storage/entity'; import { lessonFactory, setupEntities, taskFactory } from '@shared/testing'; import { CopyFilesOfParentParamBuilder } from './copy-files-of-parent-param.builder'; import { FileParamBuilder } from './files-storage-param.builder'; @@ -14,8 +15,8 @@ describe('CopyFilesOfParentParamBuilder', () => { const sourceEntity = taskFactory.buildWithId({}); const targetEntity = taskFactory.buildWithId(); - const source = FileParamBuilder.build(sourceEntity.getSchoolId(), sourceEntity); - const target = FileParamBuilder.build(targetEntity.getSchoolId(), targetEntity); + const source = FileParamBuilder.build(sourceEntity.getSchoolId(), sourceEntity, StorageLocation.SCHOOL); + const target = FileParamBuilder.build(targetEntity.getSchoolId(), targetEntity, StorageLocation.SCHOOL); const result = CopyFilesOfParentParamBuilder.build(userId, source, target); @@ -23,13 +24,15 @@ describe('CopyFilesOfParentParamBuilder', () => { userId, source: { parentType: FileRecordParentType.Task, - schoolId: sourceEntity.getSchoolId(), parentId: sourceEntity.id, + storageLocationId: sourceEntity.getSchoolId(), + storageLocation: StorageLocation.SCHOOL, }, target: { parentType: FileRecordParentType.Task, - schoolId: targetEntity.getSchoolId(), parentId: targetEntity.id, + storageLocationId: targetEntity.getSchoolId(), + storageLocation: StorageLocation.SCHOOL, }, }; @@ -41,8 +44,8 @@ describe('CopyFilesOfParentParamBuilder', () => { const sourceEntity = lessonFactory.buildWithId({}); const targetEntity = lessonFactory.buildWithId(); - const source = FileParamBuilder.build(sourceEntity.getSchoolId(), sourceEntity); - const target = FileParamBuilder.build(targetEntity.getSchoolId(), targetEntity); + const source = FileParamBuilder.build(sourceEntity.getSchoolId(), sourceEntity, StorageLocation.SCHOOL); + const target = FileParamBuilder.build(targetEntity.getSchoolId(), targetEntity, StorageLocation.SCHOOL); const result = CopyFilesOfParentParamBuilder.build(userId, source, target); @@ -50,13 +53,15 @@ describe('CopyFilesOfParentParamBuilder', () => { userId, source: { parentType: FileRecordParentType.Lesson, - schoolId: sourceEntity.getSchoolId(), parentId: sourceEntity.id, + storageLocationId: sourceEntity.getSchoolId(), + storageLocation: StorageLocation.SCHOOL, }, target: { parentType: FileRecordParentType.Lesson, - schoolId: targetEntity.getSchoolId(), parentId: targetEntity.id, + storageLocationId: targetEntity.getSchoolId(), + storageLocation: StorageLocation.SCHOOL, }, }; diff --git a/apps/server/src/modules/files-storage-client/mapper/files-storage-param.builder.spec.ts b/apps/server/src/modules/files-storage-client/mapper/files-storage-param.builder.spec.ts index 23ce4f7e175..65b90c157ba 100644 --- a/apps/server/src/modules/files-storage-client/mapper/files-storage-param.builder.spec.ts +++ b/apps/server/src/modules/files-storage-client/mapper/files-storage-param.builder.spec.ts @@ -1,4 +1,5 @@ import { FileRecordParentType } from '@infra/rabbitmq'; +import { StorageLocation } from '@modules/files-storage/entity'; import { lessonFactory, setupEntities, taskFactory } from '@shared/testing'; import { FileParamBuilder } from './files-storage-param.builder'; @@ -10,10 +11,9 @@ describe('FileParamBuilder', () => { it('Should throw for not supported parent type', () => { const schoolId = '123'; const parentType = 'abc'; - const parentId = '123'; // @ts-expect-error: Test case - expect(() => FileParamBuilder.build(schoolId, parentType, parentId)).toThrowError(); + expect(() => FileParamBuilder.build(schoolId, parentType, StorageLocation.SCHOOL)).toThrowError(); }); it('should build valid file request infos for task over shorthand task', () => { @@ -21,12 +21,13 @@ describe('FileParamBuilder', () => { const parentType = FileRecordParentType.Task; const task = taskFactory.buildWithId(); - const result = FileParamBuilder.build(schoolId, task); + const result = FileParamBuilder.build(schoolId, task, StorageLocation.SCHOOL); const expectedResult = { - schoolId, + storageLocationId: schoolId, parentType, parentId: task.id, + storageLocation: StorageLocation.SCHOOL, }; expect(result).toStrictEqual(expectedResult); @@ -37,10 +38,11 @@ describe('FileParamBuilder', () => { const parentType = FileRecordParentType.Lesson; const lesson = lessonFactory.buildWithId(); - const result = FileParamBuilder.build(schoolId, lesson); + const result = FileParamBuilder.build(schoolId, lesson, StorageLocation.SCHOOL); const expectedResult = { - schoolId, + storageLocationId: schoolId, + storageLocation: StorageLocation.SCHOOL, parentType, parentId: lesson.id, }; diff --git a/apps/server/src/modules/files-storage-client/mapper/files-storage-param.builder.ts b/apps/server/src/modules/files-storage-client/mapper/files-storage-param.builder.ts index d3e2286ec14..3a0b3d37323 100644 --- a/apps/server/src/modules/files-storage-client/mapper/files-storage-param.builder.ts +++ b/apps/server/src/modules/files-storage-client/mapper/files-storage-param.builder.ts @@ -1,13 +1,19 @@ +import { StorageLocation } from '@modules/files-storage/entity'; import { EntityId } from '@shared/domain/types'; import { EntitiesWithFiles, FileRequestInfo } from '../interfaces'; import { FilesStorageClientMapper } from './files-storage-client.mapper'; export class FileParamBuilder { - static build(schoolId: EntityId, parent: EntitiesWithFiles): FileRequestInfo { + static build( + storageLocationId: EntityId, + parent: EntitiesWithFiles, + storageLocation: StorageLocation = StorageLocation.SCHOOL + ): FileRequestInfo { const parentType = FilesStorageClientMapper.mapEntityToParentType(parent); const fileRequestInfo = { parentType, - schoolId, + storageLocationId, + storageLocation, parentId: parent.id, }; diff --git a/apps/server/src/modules/files-storage-client/service/copy-files.service.ts b/apps/server/src/modules/files-storage-client/service/copy-files.service.ts index 75f46b26fd5..4868e518160 100644 --- a/apps/server/src/modules/files-storage-client/service/copy-files.service.ts +++ b/apps/server/src/modules/files-storage-client/service/copy-files.service.ts @@ -1,4 +1,5 @@ import { CopyElementType, CopyHelperService, CopyStatus, CopyStatusEnum } from '@modules/copy-helper'; +import { StorageLocation } from '@modules/files-storage/entity'; import { Injectable } from '@nestjs/common'; import { EntityId } from '@shared/domain/types'; import { CopyFileDto } from '../dto'; @@ -23,8 +24,8 @@ export class CopyFilesService { fileUrlReplacements: FileUrlReplacement[]; fileCopyStatus: CopyStatus; }> { - const source = FileParamBuilder.build(originalEntity.getSchoolId(), originalEntity); - const target = FileParamBuilder.build(copyEntity.getSchoolId(), copyEntity); + const source = FileParamBuilder.build(originalEntity.getSchoolId(), originalEntity, StorageLocation.SCHOOL); + const target = FileParamBuilder.build(copyEntity.getSchoolId(), copyEntity, StorageLocation.SCHOOL); const copyFilesOfParentParams = CopyFilesOfParentParamBuilder.build(userId, source, target); const fileDtos = await this.filesStorageClientAdapterService.copyFilesOfParent(copyFilesOfParentParams); diff --git a/apps/server/src/modules/files-storage-client/service/files-storage-client.service.spec.ts b/apps/server/src/modules/files-storage-client/service/files-storage-client.service.spec.ts index fd30530c607..92718bf5c1d 100644 --- a/apps/server/src/modules/files-storage-client/service/files-storage-client.service.spec.ts +++ b/apps/server/src/modules/files-storage-client/service/files-storage-client.service.spec.ts @@ -10,6 +10,7 @@ import { OperationType, } from '@modules/deletion'; import { deletionRequestFactory } from '@modules/deletion/domain/testing'; +import { StorageLocation } from '@modules/files-storage/entity'; import { EventBus } from '@nestjs/cqrs'; import { Test, TestingModule } from '@nestjs/testing'; import { schoolEntityFactory, setupEntities, taskFactory } from '@shared/testing'; @@ -74,8 +75,8 @@ describe('FilesStorageClientAdapterService', () => { const sourceEntity = taskFactory.buildWithId({ school }); const targetEntity = taskFactory.buildWithId({ school }); - const source = FileParamBuilder.build(sourceEntity.getSchoolId(), sourceEntity); - const target = FileParamBuilder.build(targetEntity.getSchoolId(), targetEntity); + const source = FileParamBuilder.build(sourceEntity.getSchoolId(), sourceEntity, StorageLocation.SCHOOL); + const target = FileParamBuilder.build(targetEntity.getSchoolId(), targetEntity, StorageLocation.SCHOOL); const param = CopyFilesOfParentParamBuilder.build(userId, source, target); @@ -98,8 +99,8 @@ describe('FilesStorageClientAdapterService', () => { const sourceEntity = taskFactory.buildWithId({ school }); const targetEntity = taskFactory.buildWithId({ school }); - const source = FileParamBuilder.build(sourceEntity.getSchoolId(), sourceEntity); - const target = FileParamBuilder.build(targetEntity.getSchoolId(), targetEntity); + const source = FileParamBuilder.build(sourceEntity.getSchoolId(), sourceEntity, StorageLocation.SCHOOL); + const target = FileParamBuilder.build(targetEntity.getSchoolId(), targetEntity, StorageLocation.SCHOOL); const param = CopyFilesOfParentParamBuilder.build(userId, source, target); diff --git a/apps/server/src/modules/files-storage-client/service/files-storage.producer.spec.ts b/apps/server/src/modules/files-storage-client/service/files-storage.producer.spec.ts index 3910585ecab..12b476fb84c 100644 --- a/apps/server/src/modules/files-storage-client/service/files-storage.producer.spec.ts +++ b/apps/server/src/modules/files-storage-client/service/files-storage.producer.spec.ts @@ -1,9 +1,10 @@ import { AmqpConnection } from '@golevelup/nestjs-rabbitmq'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; +import { ErrorMapper, FileRecordParentType, FilesStorageEvents, FilesStorageExchange } from '@infra/rabbitmq'; import { ObjectId } from '@mikro-orm/mongodb'; +import { StorageLocation } from '@modules/files-storage/entity'; import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; -import { ErrorMapper, FileRecordParentType, FilesStorageEvents, FilesStorageExchange } from '@infra/rabbitmq'; import { setupEntities } from '@shared/testing'; import { LegacyLogger } from '@src/core/logger'; import { FilesStorageProducer } from './files-storage.producer'; @@ -53,12 +54,14 @@ describe('FilesStorageProducer', () => { userId: new ObjectId().toHexString(), source: { parentType: FileRecordParentType.Task, - schoolId: '633d59e1c7a36834ad61e525', + storageLocationId: '633d59e1c7a36834ad61e525', + storageLocation: StorageLocation.SCHOOL, parentId: '633d59e1c7a36834ad61e526', }, target: { parentType: FileRecordParentType.Task, - schoolId: '633d59e1c7a36834ad61e525', + storageLocationId: '633d59e1c7a36834ad61e525', + storageLocation: StorageLocation.SCHOOL, parentId: '633d59e1c7a36834ad61e527', }, }; @@ -88,12 +91,14 @@ describe('FilesStorageProducer', () => { userId, source: { parentType: FileRecordParentType.Task, - schoolId, + storageLocationId: schoolId, + storageLocation: StorageLocation.SCHOOL, parentId: parentIdSource, }, target: { parentType: FileRecordParentType.Task, - schoolId, + storageLocationId: schoolId, + storageLocation: StorageLocation.SCHOOL, parentId: parentIdTarget, }, };