From 375d03a2d60c8bd74494e243c4d3f2b67696a901 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 14 Jan 2022 08:25:41 +0000 Subject: [PATCH] Add tests for generating S3 signed upload URL --- .../src/api/controllers/static/index.js | 17 ++-- packages/server/src/api/routes/static.js | 1 - .../src/api/routes/tests/static.spec.js | 96 +++++++++++++++++++ 3 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 packages/server/src/api/routes/tests/static.spec.js diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js index bf2192446f..e3cd3f5042 100644 --- a/packages/server/src/api/controllers/static/index.js +++ b/packages/server/src/api/controllers/static/index.js @@ -108,13 +108,18 @@ exports.serveClientLibrary = async function (ctx) { } exports.getSignedUploadURL = async function (ctx) { - // Ensure datasource is valid - const { datasourceId } = ctx.params const database = new CouchDB(ctx.appId) - const datasource = await database.get(datasourceId) - if (!datasource) { + + // Ensure datasource is valid + let datasource + try { + const { datasourceId } = ctx.params + datasource = await database.get(datasourceId) + if (!datasource) { + ctx.throw(400, "The specified datasource could not be found") + } + } catch (error) { ctx.throw(400, "The specified datasource could not be found") - return } // Determine type of datasource and generate signed URL @@ -122,7 +127,7 @@ exports.getSignedUploadURL = async function (ctx) { if (datasource.source === "S3") { const { bucket, key } = ctx.request.body || {} if (!bucket || !key) { - ctx.throw(400, "datasourceId, bucket and key must be specified") + ctx.throw(400, "bucket and key values are required") return } try { diff --git a/packages/server/src/api/routes/static.js b/packages/server/src/api/routes/static.js index 2a8caff163..8a1e529a59 100644 --- a/packages/server/src/api/routes/static.js +++ b/packages/server/src/api/routes/static.js @@ -9,7 +9,6 @@ const { } = require("@budibase/backend-core/permissions") const env = require("../../environment") const { paramResource } = require("../../middleware/resourceId") -const datasourceController = require("../controllers/datasource") const router = Router() diff --git a/packages/server/src/api/routes/tests/static.spec.js b/packages/server/src/api/routes/tests/static.spec.js new file mode 100644 index 0000000000..29b476d2e5 --- /dev/null +++ b/packages/server/src/api/routes/tests/static.spec.js @@ -0,0 +1,96 @@ +jest.mock("node-fetch") +jest.mock("aws-sdk", () => ({ + config: { + update: jest.fn(), + }, + DynamoDB: { + DocumentClient: jest.fn(), + }, + S3: jest.fn(() => ({ + getSignedUrl: jest.fn(() => { + return "my-url" + }), + })), +})) + +const setup = require("./utilities") + +describe("/attachments", () => { + let request = setup.getRequest() + let config = setup.getConfig() + let app + + afterAll(setup.afterAll) + + beforeEach(async () => { + app = await config.init() + }) + + describe("generateSignedUrls", () => { + let datasource + + beforeEach(async () => { + datasource = await config.createDatasource({ + datasource: { + type: "datasource", + name: "Test", + source: "S3", + config: {}, + }, + }) + }) + + it("should be able to generate a signed upload URL", async () => { + const res = await request + .post(`/api/attachments/${datasource._id}/url`) + .send({ + bucket: "foo", + key: "bar", + }) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(res.body.signedUrl).toEqual("my-url") + }) + + it("should handle an invalid datasource ID", async () => { + const res = await request + .post(`/api/attachments/foo/url`) + .send({ + bucket: "foo", + key: "bar", + }) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(400) + expect(res.body.message).toEqual( + "The specified datasource could not be found" + ) + }) + + it("should require a bucket parameter", async () => { + const res = await request + .post(`/api/attachments/${datasource._id}/url`) + .send({ + bucket: undefined, + key: "bar", + }) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(400) + expect(res.body.message).toEqual("bucket and key values are required") + }) + + it("should require a key parameter", async () => { + const res = await request + .post(`/api/attachments/${datasource._id}/url`) + .send({ + bucket: "foo", + }) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(400) + expect(res.body.message).toEqual("bucket and key values are required") + }) + }) +})