From cf82ef057ffbe6e6b03b96d6b1ebba4bc85b513d Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 13 Mar 2024 09:53:14 +0000 Subject: [PATCH] fetch presigned url and return --- .../src/objectStore/objectStore.ts | 32 ++++++++++++++++--- packages/server/src/integrations/rest.ts | 29 +++++++++++------ 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts index ca93072286..35316b1329 100644 --- a/packages/backend-core/src/objectStore/objectStore.ts +++ b/packages/backend-core/src/objectStore/objectStore.ts @@ -110,10 +110,9 @@ export function ObjectStore( export async function makeSureBucketExists( client: any, bucketName: string, - addLifecycleConfig: boolean = false + addLifecycleConfig: boolean = true ) { bucketName = sanitizeBucket(bucketName) - try { await client .headBucket({ @@ -128,12 +127,38 @@ export async function makeSureBucketExists( await promises[bucketName] } else if (doesntExist || noAccess) { if (doesntExist) { - // bucket doesn't exist create it + // bucket doesn't exist, create it promises[bucketName] = client .createBucket({ Bucket: bucketName, }) .promise() + .then(() => { + if (addLifecycleConfig) { + return client + .putBucketLifecycleConfiguration({ + Bucket: bucketName, + LifecycleConfiguration: { + Rules: [ + { + ID: "TTL Rule", + Status: "Enabled", + NoncurrentVersionExpiration: { + NoncurrentDays: 1, + }, + Filter: { + Prefix: "", + }, + AbortIncompleteMultipartUpload: { + DaysAfterInitiation: 1, + }, + }, + ], + }, + }) + .promise() + } + }) await promises[bucketName] delete promises[bucketName] } @@ -142,7 +167,6 @@ export async function makeSureBucketExists( } } } - /** * Uploads the contents of a file given the required parameters, useful when * temp files in use (for example file uploaded as an attachment). diff --git a/packages/server/src/integrations/rest.ts b/packages/server/src/integrations/rest.ts index a45a9cf0b6..67ca917fd2 100644 --- a/packages/server/src/integrations/rest.ts +++ b/packages/server/src/integrations/rest.ts @@ -130,8 +130,19 @@ class RestIntegration implements IntegrationBase { } async parseResponse(response: any, pagination: PaginationConfig | null) { - let data, raw, headers + let data, raw, headers, presignedUrl, fileExtension + const contentType = response.headers.get("content-type") || "" + const contentDisposition = response.headers.get("content-disposition") || "" + + const filenameMatch = contentDisposition.match(/filename="?(.+)"?/i) + if (filenameMatch) { + const filename = filenameMatch[1] + const lastDotIndex = filename.lastIndexOf(".") + if (lastDotIndex !== -1) { + fileExtension = filename.slice(lastDotIndex + 1) + } + } try { if (response.status === 204) { data = [] @@ -156,15 +167,13 @@ class RestIntegration implements IntegrationBase { data = data[keys[0]] } raw = rawXml - } else if (contentType.includes("application/pdf")) { - data = await response.arrayBuffer() - raw = Buffer.from(data) - } else if (contentType.includes("image/")) { + } else if (/^(image|video|audio|application|text)\//.test(contentType)) { const data = await response.arrayBuffer() - let bucketName = `tmp-bucket-${Date.now()}` + let bucketName = `tmp-bucket-attachments-${context.getTenantId()}` - // filenames converted to UUIDs so they are unique - const processedFileName = `${uuid.v4()}.svg` + const processedFileName = `${uuid.v4()}.${ + fileExtension || contentType.split("/")[1] + }` const key = `${context.getProdAppId()}/attachments/${processedFileName}` await objectStore.upload({ @@ -173,6 +182,8 @@ class RestIntegration implements IntegrationBase { type: contentType, body: Buffer.from(data), }) + + presignedUrl = await objectStore.getPresignedUrl(bucketName, key, 600) raw = Buffer.from(data) } else { data = await response.text() @@ -195,7 +206,6 @@ class RestIntegration implements IntegrationBase { if (pagination?.responseParam) { nextCursor = get(data, pagination.responseParam) } - return { data, info: { @@ -206,6 +216,7 @@ class RestIntegration implements IntegrationBase { extra: { raw, headers, + presignedUrl, }, pagination: { cursor: nextCursor,