mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 07:10:57 +00:00
feat: setup attachment to the freight chat
This commit is contained in:
@@ -1,12 +1,19 @@
|
||||
import { SUPPORT_ATTACHMENT_RESOURCE } from "@edr/types";
|
||||
import {
|
||||
Controller,
|
||||
ForbiddenException,
|
||||
Get,
|
||||
Param,
|
||||
ParseUUIDPipe,
|
||||
Query,
|
||||
Res,
|
||||
} from "@nestjs/common";
|
||||
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiTags } from "@nestjs/swagger";
|
||||
import {
|
||||
ApiBearerAuth,
|
||||
ApiOperation,
|
||||
ApiQuery,
|
||||
ApiTags,
|
||||
} from "@nestjs/swagger";
|
||||
import { Response } from "express";
|
||||
|
||||
import { FilesService } from "./files.service";
|
||||
@@ -23,13 +30,16 @@ export class FilesController {
|
||||
// Browser inline previews (<img>/<iframe>/<a>) that can't carry the Bearer
|
||||
// token should use a short-lived signed URL instead (FilesService.signUrl).
|
||||
// TODO: enforce ownership-by-resource here next (scope the file to the
|
||||
// caller's booking/company before streaming).
|
||||
// caller's booking/company before streaming). Until that lands, any resource
|
||||
// whose files are cross-tenant sensitive must opt OUT of this route and expose
|
||||
// its own checked endpoint — see the support_message case below.
|
||||
@ApiOperation({
|
||||
summary: "Stream a file by ID",
|
||||
description:
|
||||
"Global endpoint — streams any uploaded file directly from MinIO by its UUID. " +
|
||||
"No resource context (e.g. booking ID) required. Serves inline by default so " +
|
||||
"the browser can preview it; pass ?download=1 to force a download.",
|
||||
"the browser can preview it; pass ?download=1 to force a download. " +
|
||||
"Support-chat attachments are NOT served here — use GET /support/attachments/:fileId.",
|
||||
})
|
||||
@ApiQuery({
|
||||
name: "download",
|
||||
@@ -41,7 +51,19 @@ export class FilesController {
|
||||
@Query("download") download: string | undefined,
|
||||
@Res() res: Response,
|
||||
) {
|
||||
const { stream, record } = await this.filesService.streamById(fileId);
|
||||
const record = await this.filesService.findById(fileId);
|
||||
|
||||
// Chat attachments are cross-tenant sensitive and this route has no
|
||||
// ownership check, so a leaked/guessed UUID would hand one company's file to
|
||||
// another. SupportAttachmentController scopes the caller to the owning
|
||||
// thread; refuse here rather than quietly serving the bytes.
|
||||
if (record.resource === SUPPORT_ATTACHMENT_RESOURCE) {
|
||||
throw new ForbiddenException(
|
||||
"Support chat attachments must be fetched via GET /support/attachments/:fileId.",
|
||||
);
|
||||
}
|
||||
|
||||
const { stream } = await this.filesService.streamById(fileId);
|
||||
const forceDownload = download === "1" || download === "true";
|
||||
const disposition = forceDownload ? "attachment" : "inline";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user