diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/0-54/0-54-clean-not-found-files.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/0-54/0-54-clean-not-found-files.command.ts index c9a258a08..bd5ec82aa 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/0-54/0-54-clean-not-found-files.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/0-54/0-54-clean-not-found-files.command.ts @@ -1,21 +1,14 @@ import { InjectRepository } from '@nestjs/typeorm'; -import { basename, dirname } from 'path'; - import { isNonEmptyString } from '@sniptt/guards'; import { Command } from 'nest-commander'; import { Equal, Not, Repository } from 'typeorm'; -import { - FileStorageException, - FileStorageExceptionCode, -} from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; - import { ActiveOrSuspendedWorkspacesMigrationCommandRunner, RunOnWorkspaceArgs, } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; -import { FileService } from 'src/engine/core-modules/file/services/file.service'; +import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity'; @@ -31,7 +24,7 @@ export class CleanNotFoundFilesCommand extends ActiveOrSuspendedWorkspacesMigrat @InjectRepository(Workspace, 'core') protected readonly workspaceRepository: Repository, protected readonly twentyORMGlobalManager: TwentyORMGlobalManager, - private readonly fileService: FileService, + private readonly fileStorageService: FileStorageService, ) { super(workspaceRepository, twentyORMGlobalManager); } @@ -60,25 +53,14 @@ export class CleanNotFoundFilesCommand extends ActiveOrSuspendedWorkspacesMigrat this.logger.log(`Checking if file is found ${path}`); if (path.startsWith('https://')) return true; // seed data - try { - await this.fileService.getFileStream( - dirname(path), - basename(path), - workspaceId, - ); - } catch (error) { - if ( - error instanceof FileStorageException && - error.code === FileStorageExceptionCode.FILE_NOT_FOUND - ) { - this.logger.log(`File not found`); + const isFileFound = await this.fileStorageService.checkFileExists({ + folderPath: `workspace-${workspaceId}`, + filename: path, + }); - return false; - } - } - this.logger.log(`File found`); + this.logger.log(`File found: ${isFileFound}`); - return true; + return isFileFound; } private async cleanWorkspaceLogo(workspaceId: string, dryRun: boolean) { diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/0-54/0-54-upgrade-version-command.module.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/0-54/0-54-upgrade-version-command.module.ts index eab514f45..f3586d504 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/0-54/0-54-upgrade-version-command.module.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/0-54/0-54-upgrade-version-command.module.ts @@ -7,6 +7,7 @@ import { FixStandardSelectFieldsPositionCommand } from 'src/database/commands/up import { LowercaseUserAndInvitationEmailsCommand } from 'src/database/commands/upgrade-version-command/0-54/0-54-lowercase-user-and-invitation-emails.command'; import { MigrateDefaultAvatarUrlToUserWorkspaceCommand } from 'src/database/commands/upgrade-version-command/0-54/0-54-migrate-default-avatar-url-to-user-workspace.command'; import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity'; +import { FileStorageModule } from 'src/engine/core-modules/file-storage/file-storage.module'; import { FileModule } from 'src/engine/core-modules/file/file.module'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { User } from 'src/engine/core-modules/user/user.entity'; @@ -31,6 +32,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor WorkspaceMigrationRunnerModule, WorkspaceMetadataVersionModule, FileModule, + FileStorageModule, ], providers: [ FixStandardSelectFieldsPositionCommand, diff --git a/packages/twenty-server/src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface.ts b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface.ts index 65a007624..bd0f9a107 100644 --- a/packages/twenty-server/src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface.ts @@ -21,4 +21,8 @@ export interface StorageDriver { from: { folderPath: string; filename?: string }; to: { folderPath: string; filename?: string }; }): Promise; + checkFileExists(params: { + folderPath: string; + filename: string; + }): Promise; } diff --git a/packages/twenty-server/src/engine/core-modules/file-storage/drivers/local.driver.ts b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/local.driver.ts index 104808b4e..e7fb17135 100644 --- a/packages/twenty-server/src/engine/core-modules/file-storage/drivers/local.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/local.driver.ts @@ -3,11 +3,11 @@ import * as fs from 'fs/promises'; import { dirname, join } from 'path'; import { Readable } from 'stream'; +import { StorageDriver } from 'src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface'; import { FileStorageException, FileStorageExceptionCode, } from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception'; -import { StorageDriver } from 'src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface'; export interface LocalDriverOptions { storagePath: string; @@ -162,4 +162,17 @@ export class LocalDriver implements StorageDriver { }): Promise { await this.copy(params, true); } + + async checkFileExists(params: { + folderPath: string; + filename: string; + }): Promise { + const filePath = join( + this.options.storagePath, + params.folderPath, + params.filename, + ); + + return existsSync(filePath); + } } diff --git a/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts index 0ec130cf3..219fa73ff 100644 --- a/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/drivers/s3.driver.ts @@ -395,4 +395,26 @@ export class S3Driver implements StorageDriver { return this.s3Client.createBucket(args); } + + async checkFileExists(params: { + folderPath: string; + filename: string; + }): Promise { + try { + await this.s3Client.send( + new HeadObjectCommand({ + Bucket: this.bucketName, + Key: `${params.folderPath}/${params.filename}`, + }), + ); + } catch (error) { + if (error instanceof NotFound) { + return false; + } + + throw error; + } + + return true; + } } diff --git a/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.service.ts b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.service.ts index 1b608e48a..204701196 100644 --- a/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.service.ts +++ b/packages/twenty-server/src/engine/core-modules/file-storage/file-storage.service.ts @@ -47,4 +47,11 @@ export class FileStorageService implements StorageDriver { }): Promise { return this.driver.download(params); } + + checkFileExists(params: { + folderPath: string; + filename: string; + }): Promise { + return this.driver.checkFileExists(params); + } }