add checkFileExists method in file storage service (#12229)
This commit is contained in:
@ -1,21 +1,14 @@
|
|||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { basename, dirname } from 'path';
|
|
||||||
|
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
import { Command } from 'nest-commander';
|
import { Command } from 'nest-commander';
|
||||||
import { Equal, Not, Repository } from 'typeorm';
|
import { Equal, Not, Repository } from 'typeorm';
|
||||||
|
|
||||||
import {
|
|
||||||
FileStorageException,
|
|
||||||
FileStorageExceptionCode,
|
|
||||||
} from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||||
RunOnWorkspaceArgs,
|
RunOnWorkspaceArgs,
|
||||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
} 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 { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
|
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
|
||||||
@ -31,7 +24,7 @@ export class CleanNotFoundFilesCommand extends ActiveOrSuspendedWorkspacesMigrat
|
|||||||
@InjectRepository(Workspace, 'core')
|
@InjectRepository(Workspace, 'core')
|
||||||
protected readonly workspaceRepository: Repository<Workspace>,
|
protected readonly workspaceRepository: Repository<Workspace>,
|
||||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||||
private readonly fileService: FileService,
|
private readonly fileStorageService: FileStorageService,
|
||||||
) {
|
) {
|
||||||
super(workspaceRepository, twentyORMGlobalManager);
|
super(workspaceRepository, twentyORMGlobalManager);
|
||||||
}
|
}
|
||||||
@ -60,25 +53,14 @@ export class CleanNotFoundFilesCommand extends ActiveOrSuspendedWorkspacesMigrat
|
|||||||
this.logger.log(`Checking if file is found ${path}`);
|
this.logger.log(`Checking if file is found ${path}`);
|
||||||
if (path.startsWith('https://')) return true; // seed data
|
if (path.startsWith('https://')) return true; // seed data
|
||||||
|
|
||||||
try {
|
const isFileFound = await this.fileStorageService.checkFileExists({
|
||||||
await this.fileService.getFileStream(
|
folderPath: `workspace-${workspaceId}`,
|
||||||
dirname(path),
|
filename: path,
|
||||||
basename(path),
|
});
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
if (
|
|
||||||
error instanceof FileStorageException &&
|
|
||||||
error.code === FileStorageExceptionCode.FILE_NOT_FOUND
|
|
||||||
) {
|
|
||||||
this.logger.log(`File not found`);
|
|
||||||
|
|
||||||
return false;
|
this.logger.log(`File found: ${isFileFound}`);
|
||||||
}
|
|
||||||
}
|
|
||||||
this.logger.log(`File found`);
|
|
||||||
|
|
||||||
return true;
|
return isFileFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async cleanWorkspaceLogo(workspaceId: string, dryRun: boolean) {
|
private async cleanWorkspaceLogo(workspaceId: string, dryRun: boolean) {
|
||||||
|
|||||||
@ -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 { 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 { 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 { 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 { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||||
@ -31,6 +32,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor
|
|||||||
WorkspaceMigrationRunnerModule,
|
WorkspaceMigrationRunnerModule,
|
||||||
WorkspaceMetadataVersionModule,
|
WorkspaceMetadataVersionModule,
|
||||||
FileModule,
|
FileModule,
|
||||||
|
FileStorageModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
FixStandardSelectFieldsPositionCommand,
|
FixStandardSelectFieldsPositionCommand,
|
||||||
|
|||||||
@ -21,4 +21,8 @@ export interface StorageDriver {
|
|||||||
from: { folderPath: string; filename?: string };
|
from: { folderPath: string; filename?: string };
|
||||||
to: { folderPath: string; filename?: string };
|
to: { folderPath: string; filename?: string };
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
|
checkFileExists(params: {
|
||||||
|
folderPath: string;
|
||||||
|
filename: string;
|
||||||
|
}): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,11 +3,11 @@ import * as fs from 'fs/promises';
|
|||||||
import { dirname, join } from 'path';
|
import { dirname, join } from 'path';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
|
|
||||||
|
import { StorageDriver } from 'src/engine/core-modules/file-storage/drivers/interfaces/storage-driver.interface';
|
||||||
import {
|
import {
|
||||||
FileStorageException,
|
FileStorageException,
|
||||||
FileStorageExceptionCode,
|
FileStorageExceptionCode,
|
||||||
} from 'src/engine/core-modules/file-storage/interfaces/file-storage-exception';
|
} 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 {
|
export interface LocalDriverOptions {
|
||||||
storagePath: string;
|
storagePath: string;
|
||||||
@ -162,4 +162,17 @@ export class LocalDriver implements StorageDriver {
|
|||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
await this.copy(params, true);
|
await this.copy(params, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkFileExists(params: {
|
||||||
|
folderPath: string;
|
||||||
|
filename: string;
|
||||||
|
}): Promise<boolean> {
|
||||||
|
const filePath = join(
|
||||||
|
this.options.storagePath,
|
||||||
|
params.folderPath,
|
||||||
|
params.filename,
|
||||||
|
);
|
||||||
|
|
||||||
|
return existsSync(filePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -395,4 +395,26 @@ export class S3Driver implements StorageDriver {
|
|||||||
|
|
||||||
return this.s3Client.createBucket(args);
|
return this.s3Client.createBucket(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkFileExists(params: {
|
||||||
|
folderPath: string;
|
||||||
|
filename: string;
|
||||||
|
}): Promise<boolean> {
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,4 +47,11 @@ export class FileStorageService implements StorageDriver {
|
|||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
return this.driver.download(params);
|
return this.driver.download(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkFileExists(params: {
|
||||||
|
folderPath: string;
|
||||||
|
filename: string;
|
||||||
|
}): Promise<boolean> {
|
||||||
|
return this.driver.checkFileExists(params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user