From 9cbe03fd66f8b3260c1bf705951e5e07aa2e7738 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Tue, 7 Dec 2021 22:33:26 +0000 Subject: [PATCH] Add backend for query / datasource auth --- packages/server/src/integrations/rest.ts | 43 +++++++++++++- .../src/integrations/tests/rest.spec.js | 56 +++++++++++++++++++ 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/packages/server/src/integrations/rest.ts b/packages/server/src/integrations/rest.ts index 57bd11ef9a..48ae5af0eb 100644 --- a/packages/server/src/integrations/rest.ts +++ b/packages/server/src/integrations/rest.ts @@ -13,6 +13,25 @@ const BodyTypes = { TEXT: "text", } +enum AuthType { + BASIC = "basic", + BEARER = "bearer" +} + +interface AuthConfig { + id: string + type: AuthType + config: BasicAuthConfig | BearerAuthConfig +} +interface BasicAuthConfig { + username: string, + password: string, +} + +interface BearerAuthConfig { + token: string, +} + const coreFields = { path: { type: DatasourceFieldTypes.STRING, @@ -46,6 +65,7 @@ module RestModule { defaultHeaders: { [key: string]: any } + authConfigs: AuthConfig[] } interface Request { @@ -149,12 +169,32 @@ module RestModule { } } - async _req({ path = "", queryString = "", headers = {}, json = {}, method = "GET" }) { + processAuth(authConfigId: string) { + if (!this.config.authConfigs) { + return + } + const authConfig = this.config.authConfigs.filter(authConfig => authConfig.id === authConfigId)[0] + let config + switch (authConfig.type) { + case AuthType.BASIC: + config = authConfig.config as BasicAuthConfig + this.headers.Authorization = `Basic ${Buffer.from(`${config.username}:${config.password}`).toString("base64")}` + break + case AuthType.BEARER: + config = authConfig.config as BearerAuthConfig + this.headers.Authorization = `Bearer ${config.token}` + break + } + } + + async _req({ path = "", queryString = "", headers = {}, json = {}, method = "GET", authConfigId = "" }) { this.headers = { ...this.config.defaultHeaders, ...headers, } + this.processAuth(authConfigId) + const input: any = { method, headers: this.headers } if (json && typeof json === "object" && Object.keys(json).length > 0) { input.body = JSON.stringify(json) @@ -189,5 +229,6 @@ module RestModule { module.exports = { schema: SCHEMA, integration: RestIntegration, + AuthType } } diff --git a/packages/server/src/integrations/tests/rest.spec.js b/packages/server/src/integrations/tests/rest.spec.js index 7b128a6d14..610054ccfc 100644 --- a/packages/server/src/integrations/tests/rest.spec.js +++ b/packages/server/src/integrations/tests/rest.spec.js @@ -9,6 +9,7 @@ jest.mock("node-fetch", () => ) const fetch = require("node-fetch") const RestIntegration = require("../rest") +const { AuthType } = require("../rest") class TestConfiguration { constructor(config = {}) { @@ -26,6 +27,10 @@ describe("REST Integration", () => { }) }) + // afterEach(() => { + // jest.clearAllMocks() + // }) + it("calls the create method with the correct params", async () => { const query = { path: "api", @@ -103,4 +108,55 @@ describe("REST Integration", () => { }, }) }) + + describe("authentication", () => { + const basicAuth = { + id: "basic-1", + type : AuthType.BASIC, + config : { + username: "user", + password: "password" + } + } + const bearerAuth = { + id: "bearer-1", + type : AuthType.BEARER, + config : { + "token": "mytoken" + } + } + + beforeEach(() => { + config = new TestConfiguration({ + url: BASE_URL, + authConfigs : [basicAuth, bearerAuth] + }) + }) + + it("adds basic auth", async () => { + const query = { + authConfigId: "basic-1" + } + await config.integration.read(query) + expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/?`, { + method: "GET", + headers: { + Authorization: "Basic dXNlcjpwYXNzd29yZA==" + }, + }) + }) + + it("adds bearer auth", async () => { + const query = { + authConfigId: "bearer-1" + } + await config.integration.read(query) + expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/?`, { + method: "GET", + headers: { + Authorization: "Bearer mytoken" + }, + }) + }) + }) })