diff --git a/apps/client/src/features/base/components/cells/cell-file.tsx b/apps/client/src/features/base/components/cells/cell-file.tsx index ce4d5cb2c..b279fee35 100644 --- a/apps/client/src/features/base/components/cells/cell-file.tsx +++ b/apps/client/src/features/base/components/cells/cell-file.tsx @@ -8,7 +8,7 @@ import { } from "@tabler/icons-react"; import { IBaseProperty } from "@/features/base/types/base.types"; import cellClasses from "@/features/base/styles/cells.module.css"; -import api from "@/lib/api-client"; +import { uploadFile } from "@/features/page/services/page-service"; export type FileValue = { id: string; @@ -68,21 +68,15 @@ export function CellFile({ const newFiles: FileValue[] = [...files]; + // Reuse the page-attachment upload pipeline. A base IS a page + // (isBase=true) — the server's /files/upload endpoint accepts the + // base's pageId, runs the standard pageAccessService.validateCanEdit + // check (which lines up with Base edit at the space-role level per + // the casl rules), and stores the attachment via the same flow as + // any other page attachment. for (const file of Array.from(fileList)) { try { - const formData = new FormData(); - formData.append("file", file); - formData.append("pageId", property.pageId); - - const res = await api.post( - "/bases/files/upload", - formData, - { - headers: { "Content-Type": "multipart/form-data" }, - }, - ); - - const attachment = res as unknown as FileValue; + const attachment = await uploadFile(file, property.pageId); newFiles.push({ id: attachment.id, fileName: attachment.fileName, diff --git a/apps/server/src/core/attachment/attachment.controller.ts b/apps/server/src/core/attachment/attachment.controller.ts index e2f174145..7b24cc356 100644 --- a/apps/server/src/core/attachment/attachment.controller.ts +++ b/apps/server/src/core/attachment/attachment.controller.ts @@ -47,7 +47,6 @@ import { } from '../casl/interfaces/workspace-ability.type'; import WorkspaceAbilityFactory from '../casl/abilities/workspace-ability.factory'; import { PageRepo } from '@docmost/db/repos/page/page.repo'; -import { BaseRepo } from '@docmost/db/repos/base/base.repo'; import { AttachmentRepo } from '@docmost/db/repos/attachment/attachment.repo'; import { validate as isValidUUID } from 'uuid'; import { EnvironmentService } from '../../integrations/environment/environment.service'; @@ -72,7 +71,6 @@ export class AttachmentController { private readonly workspaceAbility: WorkspaceAbilityFactory, private readonly spaceAbility: SpaceAbilityFactory, private readonly pageRepo: PageRepo, - private readonly baseRepo: BaseRepo, private readonly attachmentRepo: AttachmentRepo, private readonly environmentService: EnvironmentService, private readonly tokenService: TokenService, @@ -165,87 +163,6 @@ export class AttachmentController { } } - @UseGuards(JwtAuthGuard) - @HttpCode(HttpStatus.OK) - @Post('bases/files/upload') - @UseInterceptors(FileInterceptor) - async uploadBaseFile( - @Req() req: any, - @Res() res: FastifyReply, - @AuthUser() user: User, - @AuthWorkspace() workspace: Workspace, - ) { - const maxFileSize = bytes(this.environmentService.getFileUploadSizeLimit()); - - let file = null; - try { - file = await req.file({ - limits: { fileSize: maxFileSize, fields: 3, files: 1 }, - }); - } catch (err: any) { - this.logger.error(err.message); - if (err?.statusCode === 413) { - throw new BadRequestException( - `File too large. Exceeds the ${this.environmentService.getFileUploadSizeLimit()} limit`, - ); - } - } - - if (!file) { - throw new BadRequestException('Failed to upload file'); - } - - const pageId = file.fields?.pageId?.value; - - if (!pageId) { - throw new BadRequestException('pageId is required'); - } - - if (!isValidUUID(pageId)) { - throw new BadRequestException('Invalid pageId'); - } - - const base = await this.baseRepo.findById(pageId); - - if (!base) { - throw new NotFoundException('Base not found'); - } - - const spaceId = base.spaceId; - - const spaceAbilityCheck = await this.spaceAbility.createForUser( - user, - spaceId, - ); - if ( - spaceAbilityCheck.cannot( - SpaceCaslAction.Edit, - SpaceCaslSubject.Base, - ) - ) { - throw new ForbiddenException(); - } - - try { - const fileResponse = await this.attachmentService.uploadFile({ - filePromise: file, - spaceId: spaceId, - userId: user.id, - workspaceId: workspace.id, - }); - - return res.send(fileResponse); - } catch (err: any) { - if (err?.statusCode === 413) { - const errMessage = `File too large. Exceeds the ${this.environmentService.getFileUploadSizeLimit()} limit`; - this.logger.error(errMessage); - throw new BadRequestException(errMessage); - } - this.logger.error(err); - throw new BadRequestException('Error processing file upload.'); - } - } - @UseGuards(JwtAuthGuard) @Get('/files/:fileId/:fileName') async getFile(