diff --git a/packages/backend-core/src/environment.js b/packages/backend-core/src/environment.js index c4fc4a87c8..f628e899ad 100644 --- a/packages/backend-core/src/environment.js +++ b/packages/backend-core/src/environment.js @@ -34,6 +34,12 @@ module.exports = { COOKIE_DOMAIN: process.env.COOKIE_DOMAIN, PLATFORM_URL: process.env.PLATFORM_URL, TENANT_FEATURE_FLAGS: process.env.TENANT_FEATURE_FLAGS, + BACKUPS_BUCKET_NAME: process.env.BACKUPS_BUCKET_NAME || "backups", + APPS_BUCKET_NAME: process.env.APPS_BUCKET_NAME || "prod-budi-app-assets", + TEMPLATES_BUCKET_NAME: process.env.TEMPLATES_BUCKET_NAME || "templates", + GLOBAL_BUCKET_NAME: process.env.GLOBAL_BUCKET_NAME || "global", + GLOBAL_CLOUD_BUCKET_NAME: + process.env.GLOBAL_CLOUD_BUCKET_NAME || "prod-budi-tenant-uploads", USE_COUCH: process.env.USE_COUCH || true, isTest, isDev, diff --git a/packages/backend-core/src/objectStore/utils.js b/packages/backend-core/src/objectStore/utils.js index 1634a24981..a243553df8 100644 --- a/packages/backend-core/src/objectStore/utils.js +++ b/packages/backend-core/src/objectStore/utils.js @@ -1,12 +1,13 @@ const { join } = require("path") const { tmpdir } = require("os") +const env = require("../environment") exports.ObjectStoreBuckets = { - BACKUPS: "backups", - APPS: "prod-budi-app-assets", - TEMPLATES: "templates", - GLOBAL: "global", - GLOBAL_CLOUD: "prod-budi-tenant-uploads", + BACKUPS: env.BACKUPS_BUCKET_NAME, + APPS: env.APPS_BUCKET_NAME, + TEMPLATES: env.TEMPLATES_BUCKET_NAME, + GLOBAL: env.GLOBAL_BUCKET_NAME, + GLOBAL_CLOUD: env.GLOBAL_CLOUD_BUCKET_NAME, } exports.budibaseTempDir = function () { diff --git a/packages/builder/src/pages/builder/portal/manage/users/_components/BasicOnboardingModal.svelte b/packages/builder/src/pages/builder/portal/manage/users/_components/BasicOnboardingModal.svelte index dd3b37fce5..a4b06f45a2 100644 --- a/packages/builder/src/pages/builder/portal/manage/users/_components/BasicOnboardingModal.svelte +++ b/packages/builder/src/pages/builder/portal/manage/users/_components/BasicOnboardingModal.svelte @@ -47,7 +47,7 @@ diff --git a/packages/server/__mocks__/@google-cloud/firestore.ts b/packages/server/__mocks__/@google-cloud/firestore.ts new file mode 100644 index 0000000000..a438d6a7c5 --- /dev/null +++ b/packages/server/__mocks__/@google-cloud/firestore.ts @@ -0,0 +1,36 @@ +module FirebaseMock { + const firebase: any = {} + + firebase.Firestore = function () { + this.get = jest.fn(() => [ + { + data: jest.fn(() => ({ result: "test" })), + }, + ]) + + this.update = jest.fn() + this.set = jest.fn() + this.delete = jest.fn() + + this.doc = jest.fn(() => ({ + update: this.update, + set: this.set, + delete: this.delete, + get: jest.fn(() => ({ + data: jest.fn(() => ({ result: "test" })), + })), + id: "test_id", + })) + + this.where = jest.fn(() => ({ + get: this.get, + })) + + this.collection = jest.fn(() => ({ + doc: this.doc, + where: this.where, + })) + } + + module.exports = firebase +} diff --git a/packages/server/__mocks__/pg.ts b/packages/server/__mocks__/pg.ts index af2ae24a97..44aeabcb38 100644 --- a/packages/server/__mocks__/pg.ts +++ b/packages/server/__mocks__/pg.ts @@ -14,21 +14,13 @@ module PgMock { function Client() {} Client.prototype.query = query + Client.prototype.end = jest.fn() Client.prototype.connect = jest.fn() Client.prototype.release = jest.fn() - function Pool() {} - const on = jest.fn() - Pool.prototype.query = query - Pool.prototype.connect = jest.fn(() => { - // @ts-ignore - return new Client() - }) - Pool.prototype.on = on pg.Client = Client - pg.Pool = Pool pg.queryMock = query pg.on = on diff --git a/packages/server/src/api/controllers/row/ExternalRequest.ts b/packages/server/src/api/controllers/row/ExternalRequest.ts index d7063e590b..c8c8ae8e58 100644 --- a/packages/server/src/api/controllers/row/ExternalRequest.ts +++ b/packages/server/src/api/controllers/row/ExternalRequest.ts @@ -175,9 +175,10 @@ module External { const thisRow: Row = {} // filter the row down to what is actually the row (not joined) for (let fieldName of Object.keys(table.schema)) { - const value = row[`${table.name}.${fieldName}`] || row[fieldName] + const pathValue = row[`${table.name}.${fieldName}`] + const value = pathValue != null ? pathValue : row[fieldName] // all responses include "select col as table.col" so that overlaps are handled - if (value) { + if (value != null) { thisRow[fieldName] = value } } diff --git a/packages/server/src/integrations/firebase.ts b/packages/server/src/integrations/firebase.ts index 503dae5c95..b985797b4f 100644 --- a/packages/server/src/integrations/firebase.ts +++ b/packages/server/src/integrations/firebase.ts @@ -92,13 +92,13 @@ module Firebase { class FirebaseIntegration implements IntegrationBase { private config: FirebaseConfig - private db: Firestore + private client: Firestore constructor(config: FirebaseConfig) { this.config = config if (config.serviceAccount) { const serviceAccount = JSON.parse(config.serviceAccount) - this.db = new Firestore({ + this.client = new Firestore({ projectId: serviceAccount.project_id, credentials: { client_email: serviceAccount.client_email, @@ -106,7 +106,7 @@ module Firebase { }, }) } else { - this.db = new Firestore({ + this.client = new Firestore({ projectId: config.projectId, credentials: { client_email: config.email, @@ -118,7 +118,7 @@ module Firebase { async create(query: { json: object; extra: { [key: string]: string } }) { try { - const documentReference = this.db + const documentReference = this.client .collection(query.extra.collection) .doc() await documentReference.set({ ...query.json, id: documentReference.id }) @@ -133,7 +133,7 @@ module Firebase { async read(query: { json: object; extra: { [key: string]: string } }) { try { let snapshot - const collectionRef = this.db.collection(query.extra.collection) + const collectionRef = this.client.collection(query.extra.collection) if ( query.extra.filterField && query.extra.filter && @@ -164,19 +164,19 @@ module Firebase { extra: { [key: string]: string } }) { try { - await this.db + await this.client .collection(query.extra.collection) .doc(query.json.id) .update(query.json) return ( - await this.db + await this.client .collection(query.extra.collection) .doc(query.json.id) .get() ).data() } catch (err) { - console.error("Error writing to firebase", err) + console.error("Error writing to Firestore", err) throw err } } @@ -186,13 +186,13 @@ module Firebase { extra: { [key: string]: string } }) { try { - await this.db + await this.client .collection(query.extra.collection) .doc(query.json.id) .delete() return true } catch (err) { - console.error("Error writing to mongodb", err) + console.error("Error deleting from Firestore", err) throw err } } diff --git a/packages/server/src/integrations/index.ts b/packages/server/src/integrations/index.ts index 711e9d2262..f3e7a5fc3a 100644 --- a/packages/server/src/integrations/index.ts +++ b/packages/server/src/integrations/index.ts @@ -46,6 +46,7 @@ const INTEGRATIONS = { [SourceNames.FIREBASE]: firebase.integration, [SourceNames.GOOGLE_SHEETS]: googlesheets.integration, [SourceNames.REDIS]: redis.integration, + [SourceNames.FIREBASE]: firebase.integration, } // optionally add oracle integration if the oracle binary can be installed diff --git a/packages/server/src/integrations/postgres.ts b/packages/server/src/integrations/postgres.ts index 01257f3aa0..1da0ab31af 100644 --- a/packages/server/src/integrations/postgres.ts +++ b/packages/server/src/integrations/postgres.ts @@ -16,7 +16,7 @@ import { import { DatasourcePlus } from "./base/datasourcePlus" module PostgresModule { - const { Pool } = require("pg") + const { Client } = require("pg") const Sql = require("./base/sql") const { escapeDangerousCharacters } = require("../utilities") @@ -104,7 +104,6 @@ module PostgresModule { } class PostgresIntegration extends Sql implements DatasourcePlus { - static pool: any private readonly client: any private readonly config: PostgresConfig private index: number = 1 @@ -136,11 +135,7 @@ module PostgresModule { } : undefined, } - if (!this.pool) { - this.pool = new Pool(newConfig) - } - - this.client = this.pool + this.client = new Client(newConfig) this.setSchema() } @@ -171,16 +166,17 @@ module PostgresModule { } catch (err) { // @ts-ignore throw new Error(err) + } finally { + await this.client.end() } } - setSchema() { + async setSchema() { + await this.client.connect() if (!this.config.schema) { this.config.schema = "public" } - this.client.on("connect", (client: any) => { - client.query(`SET search_path TO ${this.config.schema}`) - }) + this.client.query(`SET search_path TO ${this.config.schema}`) this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${this.config.schema}'` } @@ -208,6 +204,8 @@ module PostgresModule { } } catch (err) { tableKeys = {} + } finally { + await this.client.close() } const columnsResponse = await this.client.query(this.COLUMNS_SQL) diff --git a/packages/server/src/integrations/tests/firebase.spec.js b/packages/server/src/integrations/tests/firebase.spec.js new file mode 100644 index 0000000000..97d3b2c0d7 --- /dev/null +++ b/packages/server/src/integrations/tests/firebase.spec.js @@ -0,0 +1,92 @@ +const firebase = require("@google-cloud/firestore") +const FirebaseIntegration = require("../firebase") +jest.mock("@google-cloud/firestore") + +class TestConfiguration { + constructor(config = {}) { + this.integration = new FirebaseIntegration.integration(config) + } +} + +describe("Firebase Integration", () => { + let config + let tableName = "Users" + + beforeEach(() => { + config = new TestConfiguration({ + serviceAccount: "{}" + }) + }) + + it("calls the create method with the correct params", async () => { + await config.integration.create({ + table: tableName, + json: { + Name: "Test Name" + }, + extra: { + collection: "test" + } + }) + expect(config.integration.client.collection).toHaveBeenCalledWith("test") + expect(config.integration.client.set).toHaveBeenCalledWith({ + Name: "Test Name", + id: "test_id" + }) + }) + + it("calls the read method with the correct params", async () => { + const response = await config.integration.read({ + table: tableName, + json: { + Name: "Test" + }, + extra: { + collection: "test", + filterField: "field", + filter: "==", + filterValue: "value", + } + }) + expect(config.integration.client.collection).toHaveBeenCalledWith("test") + expect(config.integration.client.where).toHaveBeenCalledWith("field", "==", "value") + expect(response).toEqual([{ result: "test"}]) + }) + + it("calls the update method with the correct params", async () => { + const response = await config.integration.update({ + table: tableName, + json: { + id: "test", + Name: "Test" + }, + extra: { + collection: "test" + } + }) + expect(config.integration.client.collection).toHaveBeenCalledWith("test") + expect(config.integration.client.update).toHaveBeenCalledWith({ + Name: "Test", + id: "test" + }) + expect(response).toEqual({ + result: "test" + }) + }) + + it("calls the delete method with the correct params", async () => { + const response = await config.integration.delete({ + table: tableName, + json: { + id: "test", + Name: "Test" + }, + extra: { + collection: "test" + } + }) + expect(config.integration.client.collection).toHaveBeenCalledWith("test") + expect(config.integration.client.doc).toHaveBeenCalledWith("test") + expect(config.integration.client.delete).toHaveBeenCalled() + }) +}) \ No newline at end of file diff --git a/packages/server/src/integrations/tests/postgres.spec.js b/packages/server/src/integrations/tests/postgres.spec.js index 5c0d086ce0..4ce5f12e96 100644 --- a/packages/server/src/integrations/tests/postgres.spec.js +++ b/packages/server/src/integrations/tests/postgres.spec.js @@ -15,10 +15,6 @@ describe("Postgres Integration", () => { config = new TestConfiguration() }) - it("calls the connection callback", async () => { - expect(pg.on).toHaveBeenCalledWith('connect', expect.anything()) - }) - it("calls the create method with the correct params", async () => { const sql = "insert into users (name, age) values ('Joe', 123);" await config.integration.create({