diff --git a/packages/backend-core/tests/utilities/mocks/licenses.ts b/packages/backend-core/tests/utilities/mocks/licenses.ts index 1fbda5655e..e374612f5f 100644 --- a/packages/backend-core/tests/utilities/mocks/licenses.ts +++ b/packages/backend-core/tests/utilities/mocks/licenses.ts @@ -74,6 +74,10 @@ export const useGroups = () => { return useFeature(Feature.USER_GROUPS) } +export const useEnvironmentVariables = () => { + return useFeature(Feature.ENVIRONMENT_VARIABLES) +} + // QUOTAS export const setAutomationLogsQuota = (value: number) => { diff --git a/packages/server/src/api/controllers/query/index.ts b/packages/server/src/api/controllers/query/index.ts index fd4842ea75..91e7f01afa 100644 --- a/packages/server/src/api/controllers/query/index.ts +++ b/packages/server/src/api/controllers/query/index.ts @@ -186,6 +186,8 @@ export async function preview(ctx: any) { schemaFields[key] = fieldType } } + // remove configuration before sending event + delete datasource.config await events.query.previewed(datasource, query) ctx.body = { rows, diff --git a/packages/server/src/api/routes/tests/environmentVariables.spec.ts b/packages/server/src/api/routes/tests/environmentVariables.spec.ts new file mode 100644 index 0000000000..3f32ded816 --- /dev/null +++ b/packages/server/src/api/routes/tests/environmentVariables.spec.ts @@ -0,0 +1,144 @@ +const pg = require("pg") +jest.mock("pg", () => { + return { + Client: jest.fn().mockImplementation(() => ({ + connect: jest.fn(), + query: jest.fn().mockImplementation(() => ({ rows: [] })), + end: jest.fn().mockImplementation((fn: any) => fn()), + })), + queryMock: jest.fn().mockImplementation(() => {}), + on: jest.fn(), + } +}) +import * as setup from "./utilities" +import { mocks } from "@budibase/backend-core/tests" +import { env, events } from "@budibase/backend-core" +const structures = setup.structures + +env._set("ENCRYPTION_KEY", "budibase") +mocks.licenses.useEnvironmentVariables() + +describe("/api/env/variables", () => { + let request = setup.getRequest() + let config = setup.getConfig() + + afterAll(setup.afterAll) + + beforeAll(async () => { + await config.init() + }) + + it("should be able check the status of env var API", async () => { + const res = await request + .get(`/api/env/variables/status`) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + + expect(res.body.encryptionKeyAvailable).toEqual(true) + }) + + it("should be able to create an environment variable", async () => { + await request + .post(`/api/env/variables`) + .send(structures.basicEnvironmentVariable("test", "test")) + .set(config.defaultHeaders()) + .expect(200) + }) + + it("should be able to fetch the 'test' variable name", async () => { + const res = await request + .get(`/api/env/variables`) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(res.body.variables.length).toEqual(1) + expect(res.body.variables[0]).toEqual("test") + }) + + it("should be able to update the environment variable 'test'", async () => { + const varName = "test" + await request + .patch(`/api/env/variables/${varName}`) + .send(structures.basicEnvironmentVariable("test", "test1")) + .set(config.defaultHeaders()) + .expect(200) + }) + + it("should be able to delete the environment variable 'test'", async () => { + const varName = "test" + await request + .delete(`/api/env/variables/${varName}`) + .set(config.defaultHeaders()) + .expect(200) + }) + + it("should create a datasource (using the environment variable) and query", async () => { + const datasourceBase = structures.basicDatasource() + await request + .post(`/api/env/variables`) + .send(structures.basicEnvironmentVariable("test", "test")) + .set(config.defaultHeaders()) + + datasourceBase.datasource.config = { + password: "{{ env.test }}", + } + const response = await request + .post(`/api/datasources`) + .send(datasourceBase) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(response.body.datasource._id).toBeDefined() + + const response2 = await request + .post(`/api/queries`) + .send(structures.basicQuery(response.body.datasource._id)) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(response2.body._id).toBeDefined() + }) + + it("should run a query preview and check the mocked results", async () => { + const datasourceBase = structures.basicDatasource() + await request + .post(`/api/env/variables`) + .send(structures.basicEnvironmentVariable("test", "test")) + .set(config.defaultHeaders()) + + datasourceBase.datasource.config = { + password: "{{ env.test }}", + } + const response = await request + .post(`/api/datasources`) + .send(datasourceBase) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(response.body.datasource._id).toBeDefined() + + const query = { + datasourceId: response.body.datasource._id, + parameters: {}, + fields: {}, + queryVerb: "read", + name: response.body.datasource.name, + } + const res = await request + .post(`/api/queries/preview`) + .send(query) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(res.body.rows.length).toEqual(0) + expect(events.query.previewed).toBeCalledTimes(1) + // API doesn't include config in response + delete response.body.datasource.config + expect(events.query.previewed).toBeCalledWith( + response.body.datasource, + query + ) + expect(pg.Client).toHaveBeenCalledWith({ password: "test", ssl: undefined }) + }) +}) diff --git a/packages/server/src/api/routes/tests/query.seq.spec.js b/packages/server/src/api/routes/tests/query.seq.spec.js index 699d95fea2..d7481fd224 100644 --- a/packages/server/src/api/routes/tests/query.seq.spec.js +++ b/packages/server/src/api/routes/tests/query.seq.spec.js @@ -242,6 +242,7 @@ describe("/queries", () => { }) expect(res.body.rows.length).toEqual(1) expect(events.query.previewed).toBeCalledTimes(1) + delete datasource.config expect(events.query.previewed).toBeCalledWith(datasource, query) }) diff --git a/packages/server/src/tests/utilities/structures.ts b/packages/server/src/tests/utilities/structures.ts index 6e38af47f3..c1959dc791 100644 --- a/packages/server/src/tests/utilities/structures.ts +++ b/packages/server/src/tests/utilities/structures.ts @@ -257,3 +257,15 @@ export function basicWebhook(automationId: string) { }, } } + +export function basicEnvironmentVariable( + name: string, + prod: string, + dev?: string +) { + return { + name, + production: prod, + development: dev || prod, + } +}