diff --git a/packages/bbui/src/Modal/ModalContent.svelte b/packages/bbui/src/Modal/ModalContent.svelte
index 7f2d7fbdb9..c18be1e4e1 100644
--- a/packages/bbui/src/Modal/ModalContent.svelte
+++ b/packages/bbui/src/Modal/ModalContent.svelte
@@ -21,6 +21,7 @@
export let showSecondaryButton = false
export let secondaryButtonText = undefined
export let secondaryAction = undefined
+ export let secondaryButtonWarning = false
const { hide, cancel } = getContext(Context.Modal)
let loading = false
@@ -88,8 +89,11 @@
{#if showSecondaryButton && secondaryButtonText && secondaryAction}
- {secondaryButtonText}
{/if}
diff --git a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte
index 01ba071a3f..f736d29bee 100644
--- a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte
+++ b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/PlusConfigForm.svelte
@@ -12,7 +12,7 @@
import { datasources, integrations, tables } from "stores/backend"
import CreateEditRelationship from "components/backend/Datasources/CreateEditRelationship.svelte"
import CreateExternalTableModal from "./CreateExternalTableModal.svelte"
- import ArrayRenderer from "components/common/ArrayRenderer.svelte"
+ import ArrayRenderer from "components/common/renderers/ArrayRenderer.svelte"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { goto } from "@roxi/routify"
diff --git a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/RestExtraConfigForm.svelte b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/rest/RestExtraConfigForm.svelte
similarity index 65%
rename from packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/RestExtraConfigForm.svelte
rename to packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/rest/RestExtraConfigForm.svelte
index ce3881d82c..0272463d92 100644
--- a/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/RestExtraConfigForm.svelte
+++ b/packages/builder/src/components/backend/DatasourceNavigator/TableIntegrationMenu/rest/RestExtraConfigForm.svelte
@@ -1,6 +1,7 @@
-
@@ -404,4 +449,12 @@
margin-top: var(--spacing-xl);
justify-content: center;
}
+ .auth-container {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ }
+ .auth-select {
+ width: 200px;
+ }
diff --git a/packages/server/src/api/controllers/query/import/index.ts b/packages/server/src/api/controllers/query/import/index.ts
index c99d89c2de..933d6b101c 100644
--- a/packages/server/src/api/controllers/query/import/index.ts
+++ b/packages/server/src/api/controllers/query/import/index.ts
@@ -3,7 +3,7 @@ import { queryValidation } from "../validation"
import { generateQueryID } from "../../../../db/utils"
import { ImportInfo, ImportSource } from "./sources/base"
import { OpenAPI2 } from "./sources/openapi2"
-import { Query } from './../../../../definitions/common';
+import { Query } from "./../../../../definitions/common"
import { Curl } from "./sources/curl"
interface ImportResult {
errorQueries: Query[]
diff --git a/packages/server/src/api/controllers/query/import/sources/curl.ts b/packages/server/src/api/controllers/query/import/sources/curl.ts
index ae580f65e5..61e1ae0215 100644
--- a/packages/server/src/api/controllers/query/import/sources/curl.ts
+++ b/packages/server/src/api/controllers/query/import/sources/curl.ts
@@ -29,7 +29,7 @@ const parseBody = (curl: any) => {
}
const parseCookie = (curl: any) => {
- if (curl.cookies){
+ if (curl.cookies) {
return Object.entries(curl.cookies).reduce((acc, entry) => {
const [key, value] = entry
return acc + `${key}=${value}; `
diff --git a/packages/server/src/definitions/datasource.ts b/packages/server/src/definitions/datasource.ts
index 0ca8fdcae9..148d8f2875 100644
--- a/packages/server/src/definitions/datasource.ts
+++ b/packages/server/src/definitions/datasource.ts
@@ -196,6 +196,27 @@ export interface Datasource extends Base {
}
}
+export enum AuthType {
+ BASIC = "basic",
+ BEARER = "bearer",
+}
+
+interface AuthConfig {
+ _id: string
+ name: string
+ type: AuthType
+ config: BasicAuthConfig | BearerAuthConfig
+}
+
+export interface BasicAuthConfig {
+ username: string
+ password: string
+}
+
+export interface BearerAuthConfig {
+ token: string
+}
+
export interface QueryParameter {
name: string
default: string
@@ -210,6 +231,7 @@ export interface RestQueryFields {
bodyType: string
json: object
method: string
+ authConfigId: string
}
export interface RestConfig {
@@ -217,6 +239,7 @@ export interface RestConfig {
defaultHeaders: {
[key: string]: any
}
+ authConfigs: AuthConfig[]
}
export interface Query {
diff --git a/packages/server/src/integrations/base/IntegrationBase.ts b/packages/server/src/integrations/base/IntegrationBase.ts
index d87a98c73b..bfda4fbd4d 100644
--- a/packages/server/src/integrations/base/IntegrationBase.ts
+++ b/packages/server/src/integrations/base/IntegrationBase.ts
@@ -1,6 +1,6 @@
export interface IntegrationBase {
- create?(query: any): Promise
- read?(query: any): Promise
- update?(query: any): Promise
- delete?(query: any): Promise
+ create?(query: any): Promise
+ read?(query: any): Promise
+ update?(query: any): Promise
+ delete?(query: any): Promise
}
diff --git a/packages/server/src/integrations/rest.ts b/packages/server/src/integrations/rest.ts
index 10c2c1215b..67668e7051 100644
--- a/packages/server/src/integrations/rest.ts
+++ b/packages/server/src/integrations/rest.ts
@@ -4,6 +4,9 @@ import {
QueryTypes,
RestConfig,
RestQueryFields as RestQuery,
+ AuthType,
+ BasicAuthConfig,
+ BearerAuthConfig
} from "../definitions/datasource"
import { IntegrationBase } from "./base/IntegrationBase"
@@ -147,11 +150,43 @@ module RestModule {
return complete
}
+ getAuthHeaders(authConfigId: string): { [key: string]: any }{
+ let headers: any = {}
+
+ if (this.config.authConfigs && authConfigId) {
+ const authConfig = this.config.authConfigs.filter(
+ c => c._id === authConfigId
+ )[0]
+ // check the config still exists before proceeding
+ // if not - do nothing
+ if (authConfig) {
+ let config
+ switch (authConfig.type) {
+ case AuthType.BASIC:
+ config = authConfig.config as BasicAuthConfig
+ headers.Authorization = `Basic ${Buffer.from(
+ `${config.username}:${config.password}`
+ ).toString("base64")}`
+ break
+ case AuthType.BEARER:
+ config = authConfig.config as BearerAuthConfig
+ headers.Authorization = `Bearer ${config.token}`
+ break
+ }
+ }
+ }
+
+ return headers
+ }
+
async _req(query: RestQuery) {
- const { path = "", queryString = "", headers = {}, method = "GET", disabledHeaders, bodyType, requestBody } = query
+ const { path = "", queryString = "", headers = {}, method = "GET", disabledHeaders, bodyType, requestBody, authConfigId } = query
+ const authHeaders = this.getAuthHeaders(authConfigId)
+
this.headers = {
...this.config.defaultHeaders,
...headers,
+ ...authHeaders,
}
if (disabledHeaders) {
@@ -177,7 +212,8 @@ module RestModule {
}
this.startTimeMs = performance.now()
- const response = await fetch(this.getUrl(path, queryString), input)
+ const url = this.getUrl(path, queryString)
+ const response = await fetch(url, input)
return await this.parseResponse(response)
}
@@ -205,5 +241,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 58033e68a4..6c1d989124 100644
--- a/packages/server/src/integrations/tests/rest.spec.js
+++ b/packages/server/src/integrations/tests/rest.spec.js
@@ -12,6 +12,7 @@ jest.mock("node-fetch", () =>
)
const fetch = require("node-fetch")
const RestIntegration = require("../rest")
+const { AuthType } = require("../rest")
class TestConfiguration {
constructor(config = {}) {
@@ -112,4 +113,58 @@ describe("REST Integration", () => {
body: '{"name":"test"}',
})
})
+
+ describe("authentication", () => {
+ const basicAuth = {
+ _id: "c59c14bd1898a43baa08da68959b24686",
+ name: "basic-1",
+ type : AuthType.BASIC,
+ config : {
+ username: "user",
+ password: "password"
+ }
+ }
+
+ const bearerAuth = {
+ _id: "0d91d732f34e4befabeff50b392a8ff3",
+ name: "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: "c59c14bd1898a43baa08da68959b24686"
+ }
+ await config.integration.read(query)
+ expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/?`, {
+ method: "GET",
+ headers: {
+ Authorization: "Basic dXNlcjpwYXNzd29yZA=="
+ },
+ })
+ })
+
+ it("adds bearer auth", async () => {
+ const query = {
+ authConfigId: "0d91d732f34e4befabeff50b392a8ff3"
+ }
+ await config.integration.read(query)
+ expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/?`, {
+ method: "GET",
+ headers: {
+ Authorization: "Bearer mytoken"
+ },
+ })
+ })
+ })
})