Merge pull request #5643 from Budibase/feature/small-april-tickets
Feature/small april tickets
This commit is contained in:
commit
e26d79b83c
|
@ -34,6 +34,12 @@ module.exports = {
|
||||||
COOKIE_DOMAIN: process.env.COOKIE_DOMAIN,
|
COOKIE_DOMAIN: process.env.COOKIE_DOMAIN,
|
||||||
PLATFORM_URL: process.env.PLATFORM_URL,
|
PLATFORM_URL: process.env.PLATFORM_URL,
|
||||||
TENANT_FEATURE_FLAGS: process.env.TENANT_FEATURE_FLAGS,
|
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,
|
USE_COUCH: process.env.USE_COUCH || true,
|
||||||
isTest,
|
isTest,
|
||||||
isDev,
|
isDev,
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
const { join } = require("path")
|
const { join } = require("path")
|
||||||
const { tmpdir } = require("os")
|
const { tmpdir } = require("os")
|
||||||
|
const env = require("../environment")
|
||||||
|
|
||||||
exports.ObjectStoreBuckets = {
|
exports.ObjectStoreBuckets = {
|
||||||
BACKUPS: "backups",
|
BACKUPS: env.BACKUPS_BUCKET_NAME,
|
||||||
APPS: "prod-budi-app-assets",
|
APPS: env.APPS_BUCKET_NAME,
|
||||||
TEMPLATES: "templates",
|
TEMPLATES: env.TEMPLATES_BUCKET_NAME,
|
||||||
GLOBAL: "global",
|
GLOBAL: env.GLOBAL_BUCKET_NAME,
|
||||||
GLOBAL_CLOUD: "prod-budi-tenant-uploads",
|
GLOBAL_CLOUD: env.GLOBAL_CLOUD_BUCKET_NAME,
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.budibaseTempDir = function () {
|
exports.budibaseTempDir = function () {
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
</Body>
|
</Body>
|
||||||
<Input
|
<Input
|
||||||
type="email"
|
type="email"
|
||||||
label="Username"
|
label="Email"
|
||||||
bind:value={$email}
|
bind:value={$email}
|
||||||
error={$touched && $error}
|
error={$touched && $error}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -14,21 +14,13 @@ module PgMock {
|
||||||
function Client() {}
|
function Client() {}
|
||||||
|
|
||||||
Client.prototype.query = query
|
Client.prototype.query = query
|
||||||
|
Client.prototype.end = jest.fn()
|
||||||
Client.prototype.connect = jest.fn()
|
Client.prototype.connect = jest.fn()
|
||||||
Client.prototype.release = jest.fn()
|
Client.prototype.release = jest.fn()
|
||||||
|
|
||||||
function Pool() {}
|
|
||||||
|
|
||||||
const on = jest.fn()
|
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.Client = Client
|
||||||
pg.Pool = Pool
|
|
||||||
pg.queryMock = query
|
pg.queryMock = query
|
||||||
pg.on = on
|
pg.on = on
|
||||||
|
|
||||||
|
|
|
@ -175,9 +175,10 @@ module External {
|
||||||
const thisRow: Row = {}
|
const thisRow: Row = {}
|
||||||
// filter the row down to what is actually the row (not joined)
|
// filter the row down to what is actually the row (not joined)
|
||||||
for (let fieldName of Object.keys(table.schema)) {
|
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
|
// all responses include "select col as table.col" so that overlaps are handled
|
||||||
if (value) {
|
if (value != null) {
|
||||||
thisRow[fieldName] = value
|
thisRow[fieldName] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,13 +92,13 @@ module Firebase {
|
||||||
|
|
||||||
class FirebaseIntegration implements IntegrationBase {
|
class FirebaseIntegration implements IntegrationBase {
|
||||||
private config: FirebaseConfig
|
private config: FirebaseConfig
|
||||||
private db: Firestore
|
private client: Firestore
|
||||||
|
|
||||||
constructor(config: FirebaseConfig) {
|
constructor(config: FirebaseConfig) {
|
||||||
this.config = config
|
this.config = config
|
||||||
if (config.serviceAccount) {
|
if (config.serviceAccount) {
|
||||||
const serviceAccount = JSON.parse(config.serviceAccount)
|
const serviceAccount = JSON.parse(config.serviceAccount)
|
||||||
this.db = new Firestore({
|
this.client = new Firestore({
|
||||||
projectId: serviceAccount.project_id,
|
projectId: serviceAccount.project_id,
|
||||||
credentials: {
|
credentials: {
|
||||||
client_email: serviceAccount.client_email,
|
client_email: serviceAccount.client_email,
|
||||||
|
@ -106,7 +106,7 @@ module Firebase {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.db = new Firestore({
|
this.client = new Firestore({
|
||||||
projectId: config.projectId,
|
projectId: config.projectId,
|
||||||
credentials: {
|
credentials: {
|
||||||
client_email: config.email,
|
client_email: config.email,
|
||||||
|
@ -118,7 +118,7 @@ module Firebase {
|
||||||
|
|
||||||
async create(query: { json: object; extra: { [key: string]: string } }) {
|
async create(query: { json: object; extra: { [key: string]: string } }) {
|
||||||
try {
|
try {
|
||||||
const documentReference = this.db
|
const documentReference = this.client
|
||||||
.collection(query.extra.collection)
|
.collection(query.extra.collection)
|
||||||
.doc()
|
.doc()
|
||||||
await documentReference.set({ ...query.json, id: documentReference.id })
|
await documentReference.set({ ...query.json, id: documentReference.id })
|
||||||
|
@ -133,7 +133,7 @@ module Firebase {
|
||||||
async read(query: { json: object; extra: { [key: string]: string } }) {
|
async read(query: { json: object; extra: { [key: string]: string } }) {
|
||||||
try {
|
try {
|
||||||
let snapshot
|
let snapshot
|
||||||
const collectionRef = this.db.collection(query.extra.collection)
|
const collectionRef = this.client.collection(query.extra.collection)
|
||||||
if (
|
if (
|
||||||
query.extra.filterField &&
|
query.extra.filterField &&
|
||||||
query.extra.filter &&
|
query.extra.filter &&
|
||||||
|
@ -164,19 +164,19 @@ module Firebase {
|
||||||
extra: { [key: string]: string }
|
extra: { [key: string]: string }
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
await this.db
|
await this.client
|
||||||
.collection(query.extra.collection)
|
.collection(query.extra.collection)
|
||||||
.doc(query.json.id)
|
.doc(query.json.id)
|
||||||
.update(query.json)
|
.update(query.json)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
await this.db
|
await this.client
|
||||||
.collection(query.extra.collection)
|
.collection(query.extra.collection)
|
||||||
.doc(query.json.id)
|
.doc(query.json.id)
|
||||||
.get()
|
.get()
|
||||||
).data()
|
).data()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error writing to firebase", err)
|
console.error("Error writing to Firestore", err)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,13 +186,13 @@ module Firebase {
|
||||||
extra: { [key: string]: string }
|
extra: { [key: string]: string }
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
await this.db
|
await this.client
|
||||||
.collection(query.extra.collection)
|
.collection(query.extra.collection)
|
||||||
.doc(query.json.id)
|
.doc(query.json.id)
|
||||||
.delete()
|
.delete()
|
||||||
return true
|
return true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error writing to mongodb", err)
|
console.error("Error deleting from Firestore", err)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ const INTEGRATIONS = {
|
||||||
[SourceNames.FIREBASE]: firebase.integration,
|
[SourceNames.FIREBASE]: firebase.integration,
|
||||||
[SourceNames.GOOGLE_SHEETS]: googlesheets.integration,
|
[SourceNames.GOOGLE_SHEETS]: googlesheets.integration,
|
||||||
[SourceNames.REDIS]: redis.integration,
|
[SourceNames.REDIS]: redis.integration,
|
||||||
|
[SourceNames.FIREBASE]: firebase.integration,
|
||||||
}
|
}
|
||||||
|
|
||||||
// optionally add oracle integration if the oracle binary can be installed
|
// optionally add oracle integration if the oracle binary can be installed
|
||||||
|
|
|
@ -16,7 +16,7 @@ import {
|
||||||
import { DatasourcePlus } from "./base/datasourcePlus"
|
import { DatasourcePlus } from "./base/datasourcePlus"
|
||||||
|
|
||||||
module PostgresModule {
|
module PostgresModule {
|
||||||
const { Pool } = require("pg")
|
const { Client } = require("pg")
|
||||||
const Sql = require("./base/sql")
|
const Sql = require("./base/sql")
|
||||||
const { escapeDangerousCharacters } = require("../utilities")
|
const { escapeDangerousCharacters } = require("../utilities")
|
||||||
|
|
||||||
|
@ -104,7 +104,6 @@ module PostgresModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
class PostgresIntegration extends Sql implements DatasourcePlus {
|
class PostgresIntegration extends Sql implements DatasourcePlus {
|
||||||
static pool: any
|
|
||||||
private readonly client: any
|
private readonly client: any
|
||||||
private readonly config: PostgresConfig
|
private readonly config: PostgresConfig
|
||||||
private index: number = 1
|
private index: number = 1
|
||||||
|
@ -136,11 +135,7 @@ module PostgresModule {
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
}
|
}
|
||||||
if (!this.pool) {
|
this.client = new Client(newConfig)
|
||||||
this.pool = new Pool(newConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.client = this.pool
|
|
||||||
this.setSchema()
|
this.setSchema()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,16 +166,17 @@ module PostgresModule {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
throw new Error(err)
|
throw new Error(err)
|
||||||
|
} finally {
|
||||||
|
await this.client.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setSchema() {
|
async setSchema() {
|
||||||
|
await this.client.connect()
|
||||||
if (!this.config.schema) {
|
if (!this.config.schema) {
|
||||||
this.config.schema = "public"
|
this.config.schema = "public"
|
||||||
}
|
}
|
||||||
this.client.on("connect", (client: any) => {
|
this.client.query(`SET search_path TO ${this.config.schema}`)
|
||||||
client.query(`SET search_path TO ${this.config.schema}`)
|
|
||||||
})
|
|
||||||
this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${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) {
|
} catch (err) {
|
||||||
tableKeys = {}
|
tableKeys = {}
|
||||||
|
} finally {
|
||||||
|
await this.client.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
const columnsResponse = await this.client.query(this.COLUMNS_SQL)
|
const columnsResponse = await this.client.query(this.COLUMNS_SQL)
|
||||||
|
|
|
@ -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()
|
||||||
|
})
|
||||||
|
})
|
|
@ -15,10 +15,6 @@ describe("Postgres Integration", () => {
|
||||||
config = new TestConfiguration()
|
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 () => {
|
it("calls the create method with the correct params", async () => {
|
||||||
const sql = "insert into users (name, age) values ('Joe', 123);"
|
const sql = "insert into users (name, age) values ('Joe', 123);"
|
||||||
await config.integration.create({
|
await config.integration.create({
|
||||||
|
|
Loading…
Reference in New Issue