From 4dfb74f512fc89cca88488fec0052e6dc6c7b3d5 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 14 Jan 2022 10:40:38 +0000 Subject: [PATCH] Add public URL of uploaded file to button action outputs when uploading files to S3 --- .../PropertyControls/ButtonActionEditor/manifest.json | 8 +++++++- packages/client/src/api/attachments.js | 9 +++++++-- .../client/src/components/app/forms/S3Upload.svelte | 5 +++-- packages/client/src/stores/uploads.js | 2 +- packages/client/src/utils/buttonActions.js | 5 ++++- packages/server/src/api/controllers/static/index.js | 4 +++- packages/server/src/api/routes/tests/static.spec.js | 10 ++++++---- 7 files changed, 31 insertions(+), 12 deletions(-) diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/manifest.json b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/manifest.json index 509e700bb8..ecbf0d8065 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/manifest.json +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/ButtonActionEditor/manifest.json @@ -73,7 +73,13 @@ }, { "name": "Upload File to S3", - "component": "S3Upload" + "component": "S3Upload", + "context": [ + { + "label": "File URL", + "value": "publicUrl" + } + ] } ] } \ No newline at end of file diff --git a/packages/client/src/api/attachments.js b/packages/client/src/api/attachments.js index 71624de6b2..ed9c6fe522 100644 --- a/packages/client/src/api/attachments.js +++ b/packages/client/src/api/attachments.js @@ -25,14 +25,18 @@ export const getSignedDatasourceURL = async (datasourceId, bucket, key) => { if (res.error) { throw "Could not generate signed upload URL" } - return res?.signedUrl + return res } /** * Uploads a file to an external datasource. */ export const externalUpload = async (datasourceId, bucket, key, data) => { - const signedUrl = await getSignedDatasourceURL(datasourceId, bucket, key) + const { signedUrl, publicUrl } = await getSignedDatasourceURL( + datasourceId, + bucket, + key + ) const res = await API.put({ url: signedUrl, body: data, @@ -42,4 +46,5 @@ export const externalUpload = async (datasourceId, bucket, key, data) => { if (res?.error) { throw "Could not upload file to signed URL" } + return { publicUrl } } diff --git a/packages/client/src/components/app/forms/S3Upload.svelte b/packages/client/src/components/app/forms/S3Upload.svelte index 256c6c41d5..c35fd7f194 100644 --- a/packages/client/src/components/app/forms/S3Upload.svelte +++ b/packages/client/src/components/app/forms/S3Upload.svelte @@ -71,12 +71,13 @@ const upload = async () => { loading = true try { - await API.externalUpload(datasourceId, bucket, key, data) + const res = await API.externalUpload(datasourceId, bucket, key, data) notificationStore.actions.success("File uploaded successfully") + loading = false + return res } catch (error) { notificationStore.actions.error(`Error uploading file: ${error}`) } - loading = false } onMount(() => { diff --git a/packages/client/src/stores/uploads.js b/packages/client/src/stores/uploads.js index 419d1e1c11..b41e8411b8 100644 --- a/packages/client/src/stores/uploads.js +++ b/packages/client/src/stores/uploads.js @@ -30,7 +30,7 @@ export const createUploadStore = () => { } const component = get(store).find(c => c.componentId === componentId) - await component?.callback() + return await component?.callback() } return { diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js index 6085fafec5..b17907d1d8 100644 --- a/packages/client/src/utils/buttonActions.js +++ b/packages/client/src/utils/buttonActions.js @@ -163,7 +163,10 @@ const s3UploadHandler = async action => { if (!componentId) { return } - await uploadStore.actions.processFileUpload(componentId) + const res = await uploadStore.actions.processFileUpload(componentId) + return { + publicUrl: res?.publicUrl, + } } const handlerMap = { diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js index e3cd3f5042..6a8100220c 100644 --- a/packages/server/src/api/controllers/static/index.js +++ b/packages/server/src/api/controllers/static/index.js @@ -124,6 +124,7 @@ exports.getSignedUploadURL = async function (ctx) { // Determine type of datasource and generate signed URL let signedUrl + let publicUrl if (datasource.source === "S3") { const { bucket, key } = ctx.request.body || {} if (!bucket || !key) { @@ -140,10 +141,11 @@ exports.getSignedUploadURL = async function (ctx) { }) const params = { Bucket: bucket, Key: key } signedUrl = s3.getSignedUrl("putObject", params) + publicUrl = `https://${bucket}.s3.${AWS_REGION}.amazonaws.com/${key}` } catch (error) { ctx.throw(400, error) } } - ctx.body = { signedUrl } + ctx.body = { signedUrl, publicUrl } } diff --git a/packages/server/src/api/routes/tests/static.spec.js b/packages/server/src/api/routes/tests/static.spec.js index 29b476d2e5..2ba9a6e8c8 100644 --- a/packages/server/src/api/routes/tests/static.spec.js +++ b/packages/server/src/api/routes/tests/static.spec.js @@ -41,16 +41,18 @@ describe("/attachments", () => { }) it("should be able to generate a signed upload URL", async () => { + const bucket = "foo" + const key = "bar" const res = await request .post(`/api/attachments/${datasource._id}/url`) - .send({ - bucket: "foo", - key: "bar", - }) + .send({ bucket, key }) .set(config.defaultHeaders()) .expect("Content-Type", /json/) .expect(200) expect(res.body.signedUrl).toEqual("my-url") + expect(res.body.publicUrl).toEqual( + `https://${bucket}.s3.eu-west-1.amazonaws.com/${key}` + ) }) it("should handle an invalid datasource ID", async () => {