From 8b191d6fcc34e8162830361179cd6ce65eeff6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Fri, 3 Jul 2026 13:13:14 +0200 Subject: [PATCH] chore(server): remove the five dead FileFolder values and their legacy serving pipeline (#22516) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up cleanup after #22510: shrink `FileFolder` and `fileFolderConfigs` to only folders that actually exist, so per-folder policy entries are real decisions. ## What **Remove the five dead enum values** — `ProfilePicture`, `WorkspaceLogo`, `Attachment`, `PersonPicture`, `File`. They were already marked replaced/removed in the enum, have no production write path, and `FileByIdGuard`'s `SUPPORTED_FILE_FOLDERS` allowlist already rejects them at the serving endpoint. **Delete the legacy path-based serving pipeline that existed only for them** — verified wired to no route: - `FilePathGuard` — registered as a provider in `FileModule` but applied to no controller - `extractFileInfoFromRequest` (parsed the old `/files/profile-picture/original/TOKEN/file.jpg` format) — only consumer was `FilePathGuard` - `checkFileFolder` — only consumer was `extractFileInfoFromRequest` - `settings.storage.imageCropSizes` — keyed exclusively by the three dead picture folders, zero consumers - the crop-size helpers in `utils/image.ts` (`getCropSize`, `ShortCropSize`, `CropSize`) — zero consumers outside the file; `getImageBufferFromUrl` is kept - `AllowedFolders` type — last consumer was `checkFileFolder` **Test fixtures** referencing dead folders were moved to living ones; the specs of deleted utils are deleted with them. **Generated files** (`twenty-front/src/generated-metadata/graphql.ts`, `twenty-client-sdk` schema) hand-updated to match the shrunk GraphQL enum. ## Legacy data safety Workspaces may still hold `File` rows whose `path` starts with a dead prefix (e.g. `attachment/…`). These stay inert, exactly as today: - Serving: `FileByIdGuard` rejects non-supported folders before any config lookup, and file lookups filter by `path LIKE '/%'`, so dead-prefix rows are unreachable. - Every consumer that feeds stored paths into `removeFileFolderFromFileEntityPath` (which throws on unknown prefixes) is upstream-guarded by a current-folder filter or allowlist — audited all seven call sites. - Stored legacy member `avatarUrl` strings are parsed with `extractFileIdFromUrl(url, FileFolder.CorePicture)` and already fall back to `''` for old formats; unchanged. ## GraphQL note `FileFolder` is exposed as a GraphQL enum (input of the dev-only `uploadApplicationFile` mutation, which only accepts application-code folders). Clients sending a removed value were already rejected at the resolver allowlist; they now fail GraphQL enum validation instead. No supported client sends them — the frontend only uses `CorePicture`. Net: **+10 / −301** across 17 files. https://claude.ai/code/session_01AKwhTxYFDhWhCZ4b7sf35W --- _Generated by [Claude Code](https://claude.ai/code/session_01AKwhTxYFDhWhCZ4b7sf35W)_ Review in cubic --- .../src/metadata/generated/schema.graphql | 5 -- .../src/metadata/generated/schema.ts | 7 +- .../src/generated-metadata/graphql.ts | 7 +- .../src/engine/constants/settings/index.ts | 5 -- .../settings/interfaces/settings.interface.ts | 9 --- .../engine/core-modules/file/file.module.ts | 2 - .../file/guards/file-path-guard.ts | 51 -------------- .../file/interfaces/file-folder.interface.ts | 23 ------- .../__tests__/check-file-folder.utils.spec.ts | 33 --------- .../__tests__/check-file-name.utils.spec.ts | 4 +- ...tract-file-info-from-request.utils.spec.ts | 69 ------------------- ...folder-from-file-entity-path.utils.spec.ts | 10 ++- .../set-file-response-headers.utils.spec.ts | 6 +- .../file/utils/check-file-folder.utils.ts | 22 ------ .../extract-file-info-from-request.utils.ts | 31 --------- packages/twenty-server/src/utils/image.ts | 22 ------ .../twenty-shared/src/types/FileFolder.ts | 5 -- 17 files changed, 10 insertions(+), 301 deletions(-) delete mode 100644 packages/twenty-server/src/engine/core-modules/file/guards/file-path-guard.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/file/utils/__tests__/check-file-folder.utils.spec.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/file/utils/__tests__/extract-file-info-from-request.utils.spec.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/file/utils/check-file-folder.utils.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/file/utils/extract-file-info-from-request.utils.ts diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index 2b63bb1854..1aed599b40 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -4633,12 +4633,7 @@ input CreateAppTokenInput { } enum FileFolder { - ProfilePicture - WorkspaceLogo - Attachment - PersonPicture CorePicture - File AgentChat BuiltLogicFunction BuiltFrontComponent diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index 058f93c85f..4e5782a99b 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -2997,7 +2997,7 @@ export type WorkspaceMigrationActionType = 'delete' | 'create' | 'update' export type AnalyticsType = 'PAGEVIEW' | 'TRACK' -export type FileFolder = 'ProfilePicture' | 'WorkspaceLogo' | 'Attachment' | 'PersonPicture' | 'CorePicture' | 'File' | 'AgentChat' | 'BuiltLogicFunction' | 'BuiltFrontComponent' | 'PublicAsset' | 'Source' | 'FilesField' | 'Dependencies' | 'Workflow' | 'EmailAttachment' | 'AppTarball' | 'GeneratedSdkClient' | 'Dpa' +export type FileFolder = 'CorePicture' | 'AgentChat' | 'BuiltLogicFunction' | 'BuiltFrontComponent' | 'PublicAsset' | 'Source' | 'FilesField' | 'Dependencies' | 'Workflow' | 'EmailAttachment' | 'AppTarball' | 'GeneratedSdkClient' | 'Dpa' export interface Subscription { onEventSubscription?: EventSubscription @@ -9306,12 +9306,7 @@ export const enumAnalyticsType = { } export const enumFileFolder = { - ProfilePicture: 'ProfilePicture' as const, - WorkspaceLogo: 'WorkspaceLogo' as const, - Attachment: 'Attachment' as const, - PersonPicture: 'PersonPicture' as const, CorePicture: 'CorePicture' as const, - File: 'File' as const, AgentChat: 'AgentChat' as const, BuiltLogicFunction: 'BuiltLogicFunction' as const, BuiltFrontComponent: 'BuiltFrontComponent' as const, diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 58a80667e2..781671d5c9 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1911,22 +1911,17 @@ export type FileAttachmentInput = { export enum FileFolder { AgentChat = 'AgentChat', AppTarball = 'AppTarball', - Attachment = 'Attachment', BuiltFrontComponent = 'BuiltFrontComponent', BuiltLogicFunction = 'BuiltLogicFunction', CorePicture = 'CorePicture', Dependencies = 'Dependencies', Dpa = 'Dpa', EmailAttachment = 'EmailAttachment', - File = 'File', FilesField = 'FilesField', GeneratedSdkClient = 'GeneratedSdkClient', - PersonPicture = 'PersonPicture', - ProfilePicture = 'ProfilePicture', PublicAsset = 'PublicAsset', Source = 'Source', - Workflow = 'Workflow', - WorkspaceLogo = 'WorkspaceLogo' + Workflow = 'Workflow' } export type FileWithSignedUrl = { diff --git a/packages/twenty-server/src/engine/constants/settings/index.ts b/packages/twenty-server/src/engine/constants/settings/index.ts index 2c27a81080..48af87ddf3 100644 --- a/packages/twenty-server/src/engine/constants/settings/index.ts +++ b/packages/twenty-server/src/engine/constants/settings/index.ts @@ -2,11 +2,6 @@ import { type Settings } from './interfaces/settings.interface'; export const settings: Settings = { storage: { - imageCropSizes: { - 'profile-picture': ['original'], - 'workspace-logo': ['original'], - 'person-picture': ['original'], - }, maxFileSize: '10MB', }, minLengthOfStringForDuplicateCheck: 3, diff --git a/packages/twenty-server/src/engine/constants/settings/interfaces/settings.interface.ts b/packages/twenty-server/src/engine/constants/settings/interfaces/settings.interface.ts index 17dcb34ac8..6ba487ca78 100644 --- a/packages/twenty-server/src/engine/constants/settings/interfaces/settings.interface.ts +++ b/packages/twenty-server/src/engine/constants/settings/interfaces/settings.interface.ts @@ -1,14 +1,5 @@ -import { type FileFolder } from 'twenty-shared/types'; - -import { type ShortCropSize } from 'src/utils/image'; - -type ValueOfFileFolder = `${FileFolder}`; - export interface Settings { storage: { - imageCropSizes: { - [key in ValueOfFileFolder]?: ShortCropSize[]; - }; maxFileSize: `${number}MB`; }; minLengthOfStringForDuplicateCheck: number; diff --git a/packages/twenty-server/src/engine/core-modules/file/file.module.ts b/packages/twenty-server/src/engine/core-modules/file/file.module.ts index dc9cc4f6df..cf14541e62 100644 --- a/packages/twenty-server/src/engine/core-modules/file/file.module.ts +++ b/packages/twenty-server/src/engine/core-modules/file/file.module.ts @@ -4,7 +4,6 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity'; import { FileStorageModule } from 'src/engine/core-modules/file-storage/file-storage.module'; import { FileAiChatModule } from 'src/engine/core-modules/file/file-ai-chat/file-ai-chat.module'; -import { FilePathGuard } from 'src/engine/core-modules/file/guards/file-path-guard'; import { FileDeletionJob } from 'src/engine/core-modules/file/jobs/file-deletion.job'; import { FileWorkspaceFolderDeletionJob } from 'src/engine/core-modules/file/jobs/file-workspace-folder-deletion.job'; import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module'; @@ -38,7 +37,6 @@ import { FileService } from './services/file.service'; ], providers: [ FileService, - FilePathGuard, FileByIdGuard, FileWorkspaceFolderDeletionJob, FileDeletionJob, diff --git a/packages/twenty-server/src/engine/core-modules/file/guards/file-path-guard.ts b/packages/twenty-server/src/engine/core-modules/file/guards/file-path-guard.ts deleted file mode 100644 index 8d62913cdd..0000000000 --- a/packages/twenty-server/src/engine/core-modules/file/guards/file-path-guard.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { - type CanActivate, - type ExecutionContext, - Injectable, -} from '@nestjs/common'; - -import { FileTokenJwtPayloadLegacy } from 'src/engine/core-modules/auth/types/file-token-jwt-payload-legacy.type'; -import { extractFileInfoFromRequest } from 'src/engine/core-modules/file/utils/extract-file-info-from-request.utils'; -import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; - -@Injectable() -export class FilePathGuard implements CanActivate { - constructor(private readonly jwtWrapperService: JwtWrapperService) {} - - async canActivate(context: ExecutionContext): Promise { - const request = context.switchToHttp().getRequest(); - - const { filename, fileSignature, ignoreExpirationToken } = - extractFileInfoFromRequest(request); - - if (!fileSignature) { - return false; - } - - try { - const payload = await this.jwtWrapperService.verifyJwtToken( - fileSignature, - ignoreExpirationToken ? { ignoreExpiration: true } : {}, - ); - - if ( - !payload.workspaceId || - !payload.filename || - filename !== payload.filename - ) { - return false; - } - } catch { - return false; - } - - const decodedPayload = - this.jwtWrapperService.decode(fileSignature, { - json: true, - }); - - request.workspaceId = decodedPayload.workspaceId; - - return true; - } -} diff --git a/packages/twenty-server/src/engine/core-modules/file/interfaces/file-folder.interface.ts b/packages/twenty-server/src/engine/core-modules/file/interfaces/file-folder.interface.ts index 848eb94a7f..d2dbcdf07e 100644 --- a/packages/twenty-server/src/engine/core-modules/file/interfaces/file-folder.interface.ts +++ b/packages/twenty-server/src/engine/core-modules/file/interfaces/file-folder.interface.ts @@ -1,7 +1,6 @@ import { registerEnumType } from '@nestjs/graphql'; import { FileFolder } from 'twenty-shared/types'; -import { type KebabCase } from 'type-fest'; registerEnumType(FileFolder, { name: 'FileFolder', @@ -15,30 +14,10 @@ export type FileFolderConfig = { export const IMMUTABLE_FILE_CACHE_CONTROL = 'private, max-age=86400, immutable'; export const fileFolderConfigs: Record = { - [FileFolder.ProfilePicture]: { - ignoreExpirationToken: true, - immutable: false, - }, - [FileFolder.WorkspaceLogo]: { - ignoreExpirationToken: true, - immutable: false, - }, - [FileFolder.Attachment]: { - ignoreExpirationToken: false, - immutable: false, - }, - [FileFolder.PersonPicture]: { - ignoreExpirationToken: false, - immutable: false, - }, [FileFolder.CorePicture]: { ignoreExpirationToken: true, immutable: true, }, - [FileFolder.File]: { - ignoreExpirationToken: false, - immutable: false, - }, [FileFolder.AgentChat]: { ignoreExpirationToken: false, immutable: true, @@ -88,5 +67,3 @@ export const fileFolderConfigs: Record = { immutable: true, }, }; - -export type AllowedFolders = KebabCase; diff --git a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/check-file-folder.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/check-file-folder.utils.spec.ts deleted file mode 100644 index ebfd582b31..0000000000 --- a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/check-file-folder.utils.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BadRequestException } from '@nestjs/common'; - -import { FileFolder } from 'twenty-shared/types'; - -import { checkFileFolder } from 'src/engine/core-modules/file/utils/check-file-folder.utils'; - -describe('checkFileFolder', () => { - it('should return the root folder when it is allowed', () => { - expect(checkFileFolder(`${FileFolder.Attachment}/file.txt`)).toBe( - FileFolder.Attachment, - ); - }); - - it('should throw BadRequestException for disallowed folders', () => { - expect(() => checkFileFolder('invalid-folder/file.txt')).toThrow( - BadRequestException, - ); - }); - - it('should sanitize null characters in file path', () => { - expect(() => checkFileFolder('\0invalid-folder/file.txt')).toThrow( - BadRequestException, - ); - }); - - it('should handle edge cases like empty file path', () => { - expect(() => checkFileFolder('')).toThrow(BadRequestException); - }); - - it('should handle cases where filePath has no folder', () => { - expect(() => checkFileFolder('file.txt')).toThrow(BadRequestException); - }); -}); diff --git a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/check-file-name.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/check-file-name.utils.spec.ts index 2ee053c8a0..609ac094fb 100644 --- a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/check-file-name.utils.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/check-file-name.utils.spec.ts @@ -4,10 +4,10 @@ import { checkFilename } from 'src/engine/core-modules/file/utils/check-file-nam describe('checkFilename', () => { it('should return sanitized filename', () => { - const filename = `${FileFolder.Attachment}\0.png`; + const filename = `${FileFolder.FilesField}\0.png`; const sanitizedFilename = checkFilename(filename); - expect(sanitizedFilename).toBe(`${FileFolder.Attachment}.png`); + expect(sanitizedFilename).toBe(`${FileFolder.FilesField}.png`); }); it('should throw an error for invalid filename', () => { diff --git a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/extract-file-info-from-request.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/extract-file-info-from-request.utils.spec.ts deleted file mode 100644 index cc4179f2f4..0000000000 --- a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/extract-file-info-from-request.utils.spec.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { type Request } from 'express'; - -import { checkFileFolder } from 'src/engine/core-modules/file/utils/check-file-folder.utils'; -import { checkFilename } from 'src/engine/core-modules/file/utils/check-file-name.utils'; -import { extractFileInfoFromRequest } from 'src/engine/core-modules/file/utils/extract-file-info-from-request.utils'; - -jest.mock('src/engine/core-modules/file/utils/check-file-name.utils', () => ({ - checkFilename: jest.fn(), -})); - -jest.mock('src/engine/core-modules/file/utils/check-file-folder.utils', () => ({ - checkFileFolder: jest.fn(), -})); - -jest.mock( - 'src/engine/core-modules/file/interfaces/file-folder.interface', - () => ({ - fileFolderConfigs: { - attachment: { ignoreExpirationToken: false }, - 'profile-picture': { ignoreExpirationToken: true }, - }, - }), -); - -describe('extractFileInfoFromRequest', () => { - it('should extract all file info correctly from 3-segment path', () => { - const mockRequest = { - path: '/files/attachment/filesig123/myfile.txt', - } as unknown as Request; - - (checkFilename as jest.Mock).mockReturnValue('validated-file.txt'); - (checkFileFolder as jest.Mock).mockReturnValue('attachment'); - - const result = extractFileInfoFromRequest(mockRequest); - - expect(checkFilename).toHaveBeenCalledWith('myfile.txt'); - expect(checkFileFolder).toHaveBeenCalledWith('attachment'); - - expect(result).toEqual({ - filename: 'validated-file.txt', - fileSignature: 'filesig123', - rawFolder: 'attachment', - fileFolder: 'attachment', - ignoreExpirationToken: false, - }); - }); - - it('should extract all file info correctly from 4-segment path with size', () => { - const mockRequest = { - path: '/files/profile-picture/original/filesig456/avatar.jpg', - } as unknown as Request; - - (checkFilename as jest.Mock).mockReturnValue('validated-avatar.jpg'); - (checkFileFolder as jest.Mock).mockReturnValue('profile-picture'); - - const result = extractFileInfoFromRequest(mockRequest); - - expect(checkFilename).toHaveBeenCalledWith('avatar.jpg'); - expect(checkFileFolder).toHaveBeenCalledWith('profile-picture/original'); - - expect(result).toEqual({ - filename: 'validated-avatar.jpg', - fileSignature: 'filesig456', - rawFolder: 'profile-picture/original', - fileFolder: 'profile-picture', - ignoreExpirationToken: true, - }); - }); -}); diff --git a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/remove-file-folder-from-file-entity-path.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/remove-file-folder-from-file-entity-path.utils.spec.ts index d2c96bb076..7ddb2a3c5c 100644 --- a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/remove-file-folder-from-file-entity-path.utils.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/remove-file-folder-from-file-entity-path.utils.spec.ts @@ -7,14 +7,14 @@ import { removeFileFolderFromFileEntityPath } from 'src/engine/core-modules/file describe('removeFileFolderFromFileEntityPath', () => { it('should remove file folder prefix from path', () => { expect( - removeFileFolderFromFileEntityPath(`${FileFolder.Attachment}/file.txt`), + removeFileFolderFromFileEntityPath(`${FileFolder.FilesField}/file.txt`), ).toBe('file.txt'); }); it('should handle nested paths correctly', () => { expect( removeFileFolderFromFileEntityPath( - `${FileFolder.Attachment}/subfolder/file.txt`, + `${FileFolder.FilesField}/subfolder/file.txt`, ), ).toBe('subfolder/file.txt'); }); @@ -22,14 +22,12 @@ describe('removeFileFolderFromFileEntityPath', () => { it('should work with different valid file folders', () => { expect( removeFileFolderFromFileEntityPath( - `${FileFolder.ProfilePicture}/avatar.png`, + `${FileFolder.CorePicture}/avatar.png`, ), ).toBe('avatar.png'); expect( - removeFileFolderFromFileEntityPath( - `${FileFolder.WorkspaceLogo}/logo.svg`, - ), + removeFileFolderFromFileEntityPath(`${FileFolder.Workflow}/logo.svg`), ).toBe('logo.svg'); expect( diff --git a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/set-file-response-headers.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/set-file-response-headers.utils.spec.ts index 86e449af1c..a2db42b2b3 100644 --- a/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/set-file-response-headers.utils.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/file/utils/__tests__/set-file-response-headers.utils.spec.ts @@ -108,12 +108,10 @@ describe('setFileResponseHeaders', () => { ); it.each([ - FileFolder.ProfilePicture, - FileFolder.WorkspaceLogo, - FileFolder.PersonPicture, - FileFolder.Attachment, FileFolder.PublicAsset, FileFolder.AppTarball, + FileFolder.Source, + FileFolder.BuiltFrontComponent, ])('should not set Cache-Control for mutable folder %s', (fileFolder) => { const res = createMockResponse(); diff --git a/packages/twenty-server/src/engine/core-modules/file/utils/check-file-folder.utils.ts b/packages/twenty-server/src/engine/core-modules/file/utils/check-file-folder.utils.ts deleted file mode 100644 index 5218e53da9..0000000000 --- a/packages/twenty-server/src/engine/core-modules/file/utils/check-file-folder.utils.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { BadRequestException } from '@nestjs/common'; - -import { FileFolder } from 'twenty-shared/types'; - -import { type AllowedFolders } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; - -import { kebabCase } from 'src/utils/kebab-case'; - -export const checkFileFolder = (filePath: string): FileFolder => { - const allowedFolders = Object.values(FileFolder).map((value) => - kebabCase(value), - ); - - const sanitizedFilePath = filePath.replace(/\0/g, ''); - const [rootFolder] = sanitizedFilePath.split('/'); - - if (!allowedFolders.includes(rootFolder as AllowedFolders)) { - throw new BadRequestException(`Folder ${rootFolder} is not allowed`); - } - - return rootFolder as FileFolder; -}; diff --git a/packages/twenty-server/src/engine/core-modules/file/utils/extract-file-info-from-request.utils.ts b/packages/twenty-server/src/engine/core-modules/file/utils/extract-file-info-from-request.utils.ts deleted file mode 100644 index 15e481f005..0000000000 --- a/packages/twenty-server/src/engine/core-modules/file/utils/extract-file-info-from-request.utils.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { type Request } from 'express'; - -import { fileFolderConfigs } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; - -import { checkFileFolder } from 'src/engine/core-modules/file/utils/check-file-folder.utils'; -import { checkFilename } from 'src/engine/core-modules/file/utils/check-file-name.utils'; - -export const extractFileInfoFromRequest = (request: Request) => { - // Ex: /files/profile-picture/original/TOKEN/file.jpg - const pathSegments = request.path.split('/').filter((segment) => segment); - - const segments = pathSegments.slice(1); - - const filename = checkFilename(segments[segments.length - 1]); - const fileSignature = segments[segments.length - 2]; - const folderSegments = segments.slice(0, segments.length - 2); - const rawFolder = folderSegments.join('/'); - - const fileFolder = checkFileFolder(rawFolder); - - const ignoreExpirationToken = - fileFolderConfigs[fileFolder].ignoreExpirationToken; - - return { - filename, - fileSignature, - rawFolder, - fileFolder, - ignoreExpirationToken, - }; -}; diff --git a/packages/twenty-server/src/utils/image.ts b/packages/twenty-server/src/utils/image.ts index f63b63be11..3424dfced0 100644 --- a/packages/twenty-server/src/utils/image.ts +++ b/packages/twenty-server/src/utils/image.ts @@ -1,28 +1,6 @@ import { type AxiosInstance } from 'axios'; import { isNonEmptyString } from '@sniptt/guards'; -const cropRegex = /([w|h])([0-9]+)/; - -export type ShortCropSize = `${'w' | 'h'}${number}` | 'original'; - -export interface CropSize { - type: 'width' | 'height'; - value: number; -} - -export const getCropSize = (value: ShortCropSize): CropSize | null => { - const match = value.match(cropRegex); - - if (value === 'original' || match === null) { - return null; - } - - return { - type: match[1] === 'w' ? 'width' : 'height', - value: +match[2], - }; -}; - export const getImageBufferFromUrl = async ( url: string, axiosInstance: AxiosInstance, diff --git a/packages/twenty-shared/src/types/FileFolder.ts b/packages/twenty-shared/src/types/FileFolder.ts index d4dcb446aa..029bf3da7d 100644 --- a/packages/twenty-shared/src/types/FileFolder.ts +++ b/packages/twenty-shared/src/types/FileFolder.ts @@ -1,10 +1,5 @@ export enum FileFolder { - ProfilePicture = 'profile-picture', // replaced by core-picture - WorkspaceLogo = 'workspace-logo', // replaced by core-picture - Attachment = 'attachment', // replaced by files-field - PersonPicture = 'person-picture', // replaced by files-field CorePicture = 'core-picture', - File = 'file', // removed AgentChat = 'agent-chat', BuiltLogicFunction = 'built-logic-function', BuiltFrontComponent = 'built-front-component',