mirror of https://github.com/Budibase/budibase.git
committed by
GitHub
56 changed files with 981 additions and 292 deletions
@ -1,38 +1,42 @@ |
|||
<script> |
|||
import { createEventDispatcher } from 'svelte' |
|||
import { createEventDispatcher } from "svelte" |
|||
import Colorpicker from "@budibase/colorpicker" |
|||
|
|||
const dispatch = createEventDispatcher(); |
|||
|
|||
const dispatch = createEventDispatcher() |
|||
|
|||
export let value |
|||
|
|||
const WAIT = 150; |
|||
|
|||
|
|||
const WAIT = 150 |
|||
|
|||
function throttle(callback, wait, immediate = false) { |
|||
let timeout = null |
|||
let timeout = null |
|||
let initialCall = true |
|||
|
|||
|
|||
return function() { |
|||
const callNow = immediate && initialCall |
|||
const next = () => { |
|||
callback.apply(this, arguments) |
|||
timeout = null |
|||
} |
|||
|
|||
if (callNow) { |
|||
|
|||
if (callNow) { |
|||
initialCall = false |
|||
next() |
|||
} |
|||
|
|||
|
|||
if (!timeout) { |
|||
timeout = setTimeout(next, wait) |
|||
} |
|||
} |
|||
} |
|||
|
|||
const onChange = throttle(e => { |
|||
dispatch('change', e.detail) |
|||
}, WAIT, true) |
|||
|
|||
const onChange = throttle( |
|||
e => { |
|||
dispatch("change", e.detail) |
|||
}, |
|||
WAIT, |
|||
true |
|||
) |
|||
</script> |
|||
|
|||
<Colorpicker value={value || '#C4C4C4'} on:change={onChange} /> |
|||
|
|||
@ -0,0 +1,18 @@ |
|||
class Email { |
|||
constructor() { |
|||
this.apiKey = null |
|||
} |
|||
|
|||
setApiKey(apiKey) { |
|||
this.apiKey = apiKey |
|||
} |
|||
|
|||
async send(msg) { |
|||
if (msg.to === "invalid@test.com") { |
|||
throw "Invalid" |
|||
} |
|||
return msg |
|||
} |
|||
} |
|||
|
|||
module.exports = new Email() |
|||
@ -1,17 +1,35 @@ |
|||
const fetch = jest.requireActual("node-fetch") |
|||
|
|||
module.exports = async (url, opts) => { |
|||
// mocked data based on url
|
|||
if (url.includes("api/apps")) { |
|||
function json(body, status = 200) { |
|||
return { |
|||
status, |
|||
json: async () => { |
|||
return { |
|||
app1: { |
|||
url: "/app1", |
|||
}, |
|||
} |
|||
return body |
|||
}, |
|||
} |
|||
} |
|||
|
|||
// mocked data based on url
|
|||
if (url.includes("api/apps")) { |
|||
return json({ |
|||
app1: { |
|||
url: "/app1", |
|||
}, |
|||
}) |
|||
} else if (url.includes("test.com")) { |
|||
return json({ |
|||
body: opts.body, |
|||
url, |
|||
method: opts.method, |
|||
}) |
|||
} else if (url.includes("invalid.com")) { |
|||
return json( |
|||
{ |
|||
invalid: true, |
|||
}, |
|||
404 |
|||
) |
|||
} |
|||
return fetch(url, opts) |
|||
} |
|||
|
|||
@ -1,15 +0,0 @@ |
|||
module.exports = { |
|||
table: require("../../../controllers/table"), |
|||
row: require("../../../controllers/row"), |
|||
role: require("../../../controllers/role"), |
|||
perms: require("../../../controllers/permission"), |
|||
view: require("../../../controllers/view"), |
|||
app: require("../../../controllers/application"), |
|||
user: require("../../../controllers/user"), |
|||
automation: require("../../../controllers/automation"), |
|||
datasource: require("../../../controllers/datasource"), |
|||
query: require("../../../controllers/query"), |
|||
screen: require("../../../controllers/screen"), |
|||
webhook: require("../../../controllers/webhook"), |
|||
layout: require("../../../controllers/layout"), |
|||
} |
|||
@ -0,0 +1,152 @@ |
|||
const automation = require("../index") |
|||
const usageQuota = require("../../utilities/usageQuota") |
|||
const thread = require("../thread") |
|||
const triggers = require("../triggers") |
|||
const { basicAutomation, basicTable } = require("../../tests/utilities/structures") |
|||
const { wait } = require("../../utilities") |
|||
const env = require("../../environment") |
|||
const { makePartial } = require("../../tests/utilities") |
|||
const { cleanInputValues } = require("../automationUtils") |
|||
const setup = require("./utilities") |
|||
|
|||
let workerJob |
|||
|
|||
jest.mock("../../utilities/usageQuota") |
|||
usageQuota.getAPIKey.mockReturnValue({ apiKey: "test" }) |
|||
jest.mock("../thread") |
|||
jest.spyOn(global.console, "error") |
|||
jest.mock("worker-farm", () => { |
|||
return () => { |
|||
const value = jest |
|||
.fn() |
|||
.mockReturnValueOnce(undefined) |
|||
.mockReturnValueOnce("Error") |
|||
return (input, callback) => { |
|||
workerJob = input |
|||
if (callback) { |
|||
callback(value()) |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
|
|||
describe("Run through some parts of the automations system", () => { |
|||
let config = setup.getConfig() |
|||
|
|||
beforeEach(async () => { |
|||
await automation.init() |
|||
await config.init() |
|||
}) |
|||
|
|||
afterAll(setup.afterAll) |
|||
|
|||
it("should be able to init in builder", async () => { |
|||
await triggers.externalTrigger(basicAutomation(), { a: 1 }) |
|||
await wait(100) |
|||
expect(workerJob).toBeUndefined() |
|||
expect(thread).toHaveBeenCalled() |
|||
}) |
|||
|
|||
it("should be able to init in cloud", async () => { |
|||
env.CLOUD = true |
|||
env.BUDIBASE_ENVIRONMENT = "PRODUCTION" |
|||
await triggers.externalTrigger(basicAutomation(), { a: 1 }) |
|||
await wait(100) |
|||
// haven't added a mock implementation so getAPIKey of usageQuota just returns undefined
|
|||
expect(usageQuota.update).toHaveBeenCalledWith("test", "automationRuns", 1) |
|||
expect(workerJob).toBeDefined() |
|||
env.BUDIBASE_ENVIRONMENT = "JEST" |
|||
env.CLOUD = false |
|||
}) |
|||
|
|||
it("try error scenario", async () => { |
|||
env.CLOUD = true |
|||
env.BUDIBASE_ENVIRONMENT = "PRODUCTION" |
|||
// the second call will throw an error
|
|||
await triggers.externalTrigger(basicAutomation(), { a: 1 }) |
|||
await wait(100) |
|||
expect(console.error).toHaveBeenCalled() |
|||
env.BUDIBASE_ENVIRONMENT = "JEST" |
|||
env.CLOUD = false |
|||
}) |
|||
|
|||
it("should be able to check triggering row filling", async () => { |
|||
const automation = basicAutomation() |
|||
let table = basicTable() |
|||
table.schema.boolean = { |
|||
type: "boolean", |
|||
constraints: { |
|||
type: "boolean", |
|||
}, |
|||
} |
|||
table.schema.number = { |
|||
type: "number", |
|||
constraints: { |
|||
type: "number", |
|||
}, |
|||
} |
|||
table.schema.datetime = { |
|||
type: "datetime", |
|||
constraints: { |
|||
type: "datetime", |
|||
}, |
|||
} |
|||
table = await config.createTable(table) |
|||
automation.definition.trigger.inputs.tableId = table._id |
|||
const params = await triggers.fillRowOutput(automation, { appId: config.getAppId() }) |
|||
expect(params.row).toBeDefined() |
|||
const date = new Date(params.row.datetime) |
|||
expect(typeof params.row.name).toBe("string") |
|||
expect(typeof params.row.boolean).toBe("boolean") |
|||
expect(typeof params.row.number).toBe("number") |
|||
expect(date.getFullYear()).toBe(1970) |
|||
}) |
|||
|
|||
it("should check coercion", async () => { |
|||
const table = await config.createTable() |
|||
const automation = basicAutomation() |
|||
automation.definition.trigger.inputs.tableId = table._id |
|||
automation.definition.trigger.stepId = "APP" |
|||
automation.definition.trigger.inputs.fields = { a: "number" } |
|||
await triggers.externalTrigger(automation, { |
|||
appId: config.getAppId(), |
|||
fields: { |
|||
a: "1" |
|||
} |
|||
}) |
|||
await wait(100) |
|||
expect(thread).toHaveBeenCalledWith(makePartial({ |
|||
data: { |
|||
event: { |
|||
fields: { |
|||
a: 1 |
|||
} |
|||
} |
|||
} |
|||
})) |
|||
}) |
|||
|
|||
it("should be able to clean inputs with the utilities", () => { |
|||
// can't clean without a schema
|
|||
let output = cleanInputValues({a: "1"}) |
|||
expect(output.a).toBe("1") |
|||
output = cleanInputValues({a: "1", b: "true", c: "false", d: 1, e: "help"}, { |
|||
properties: { |
|||
a: { |
|||
type: "number", |
|||
}, |
|||
b: { |
|||
type: "boolean", |
|||
}, |
|||
c: { |
|||
type: "boolean", |
|||
} |
|||
} |
|||
}) |
|||
expect(output.a).toBe(1) |
|||
expect(output.b).toBe(true) |
|||
expect(output.c).toBe(false) |
|||
expect(output.d).toBe(1) |
|||
expect(output.e).toBe("help") |
|||
}) |
|||
}) |
|||
@ -0,0 +1,57 @@ |
|||
const usageQuota = require("../../utilities/usageQuota") |
|||
const env = require("../../environment") |
|||
const setup = require("./utilities") |
|||
|
|||
jest.mock("../../utilities/usageQuota") |
|||
|
|||
describe("test the create row action", () => { |
|||
let table, row |
|||
let config = setup.getConfig() |
|||
|
|||
beforeEach(async () => { |
|||
await config.init() |
|||
table = await config.createTable() |
|||
row = { |
|||
tableId: table._id, |
|||
name: "test", |
|||
description: "test", |
|||
} |
|||
}) |
|||
|
|||
afterAll(setup.afterAll) |
|||
|
|||
it("should be able to run the action", async () => { |
|||
const res = await setup.runStep(setup.actions.CREATE_ROW.stepId, { |
|||
row, |
|||
}) |
|||
expect(res.id).toBeDefined() |
|||
expect(res.revision).toBeDefined() |
|||
const gottenRow = await config.getRow(table._id, res.id) |
|||
expect(gottenRow.name).toEqual("test") |
|||
expect(gottenRow.description).toEqual("test") |
|||
}) |
|||
|
|||
it("should return an error (not throw) when bad info provided", async () => { |
|||
const res = await setup.runStep(setup.actions.CREATE_ROW.stepId, { |
|||
row: { |
|||
tableId: "invalid", |
|||
invalid: "invalid", |
|||
} |
|||
}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
|
|||
it("check usage quota attempts", async () => { |
|||
env.CLOUD = true |
|||
await setup.runStep(setup.actions.CREATE_ROW.stepId, { |
|||
row |
|||
}) |
|||
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "rows", 1) |
|||
env.CLOUD = false |
|||
}) |
|||
|
|||
it("should check invalid inputs return an error", async () => { |
|||
const res = await setup.runStep(setup.actions.CREATE_ROW.stepId, {}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
}) |
|||
@ -0,0 +1,43 @@ |
|||
const usageQuota = require("../../utilities/usageQuota") |
|||
const env = require("../../environment") |
|||
const setup = require("./utilities") |
|||
const { BUILTIN_ROLE_IDS } = require("../../utilities/security/roles") |
|||
const { ViewNames } = require("../../db/utils") |
|||
|
|||
jest.mock("../../utilities/usageQuota") |
|||
|
|||
describe("test the create user action", () => { |
|||
let config = setup.getConfig() |
|||
let user |
|||
|
|||
beforeEach(async () => { |
|||
await config.init() |
|||
user = { |
|||
email: "test@test.com", |
|||
password: "password", |
|||
roleId: BUILTIN_ROLE_IDS.POWER |
|||
} |
|||
}) |
|||
|
|||
afterAll(setup.afterAll) |
|||
|
|||
it("should be able to run the action", async () => { |
|||
const res = await setup.runStep(setup.actions.CREATE_USER.stepId, user) |
|||
expect(res.id).toBeDefined() |
|||
expect(res.revision).toBeDefined() |
|||
const userDoc = await config.getRow(ViewNames.USERS, res.id) |
|||
expect(userDoc.email).toEqual(user.email) |
|||
}) |
|||
|
|||
it("should return an error if no inputs provided", async () => { |
|||
const res = await setup.runStep(setup.actions.CREATE_USER.stepId, {}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
|
|||
it("check usage quota attempts", async () => { |
|||
env.CLOUD = true |
|||
await setup.runStep(setup.actions.CREATE_USER.stepId, user) |
|||
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "users", 1) |
|||
env.CLOUD = false |
|||
}) |
|||
}) |
|||
@ -0,0 +1,12 @@ |
|||
const setup = require("./utilities") |
|||
|
|||
describe("test the delay logic", () => { |
|||
it("should be able to run the delay", async () => { |
|||
const time = 100 |
|||
const before = Date.now() |
|||
await setup.runStep(setup.logic.DELAY.stepId, { time: time }) |
|||
const now = Date.now() |
|||
// divide by two just so that test will always pass as long as there was some sort of delay
|
|||
expect(now - before).toBeGreaterThanOrEqual(time / 2) |
|||
}) |
|||
}) |
|||
@ -0,0 +1,58 @@ |
|||
const usageQuota = require("../../utilities/usageQuota") |
|||
const env = require("../../environment") |
|||
const setup = require("./utilities") |
|||
|
|||
jest.mock("../../utilities/usageQuota") |
|||
|
|||
describe("test the delete row action", () => { |
|||
let table, row, inputs |
|||
let config = setup.getConfig() |
|||
|
|||
beforeEach(async () => { |
|||
await config.init() |
|||
table = await config.createTable() |
|||
row = await config.createRow() |
|||
inputs = { |
|||
tableId: table._id, |
|||
id: row._id, |
|||
revision: row._rev, |
|||
} |
|||
}) |
|||
|
|||
afterAll(setup.afterAll) |
|||
|
|||
it("should be able to run the action", async () => { |
|||
const res = await setup.runStep(setup.actions.DELETE_ROW.stepId, inputs) |
|||
expect(res.success).toEqual(true) |
|||
expect(res.response).toBeDefined() |
|||
expect(res.row._id).toEqual(row._id) |
|||
let error |
|||
try { |
|||
await config.getRow(table._id, res.id) |
|||
} catch (err) { |
|||
error = err |
|||
} |
|||
expect(error).toBeDefined() |
|||
}) |
|||
|
|||
it("check usage quota attempts", async () => { |
|||
env.CLOUD = true |
|||
await setup.runStep(setup.actions.DELETE_ROW.stepId, inputs) |
|||
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "rows", -1) |
|||
env.CLOUD = false |
|||
}) |
|||
|
|||
it("should check invalid inputs return an error", async () => { |
|||
const res = await setup.runStep(setup.actions.DELETE_ROW.stepId, {}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
|
|||
it("should return an error when table doesn't exist", async () => { |
|||
const res = await setup.runStep(setup.actions.DELETE_ROW.stepId, { |
|||
tableId: "invalid", |
|||
id: "invalid", |
|||
revision: "invalid", |
|||
}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
}) |
|||
@ -0,0 +1,48 @@ |
|||
const setup = require("./utilities") |
|||
const { LogicConditions } = require("../steps/filter") |
|||
|
|||
describe("test the filter logic", () => { |
|||
async function checkFilter(field, condition, value, pass = true) { |
|||
let res = await setup.runStep(setup.logic.FILTER.stepId, |
|||
{ field, condition, value } |
|||
) |
|||
expect(res.success).toEqual(pass) |
|||
} |
|||
|
|||
it("should be able test equality", async () => { |
|||
await checkFilter("hello", LogicConditions.EQUAL, "hello", true) |
|||
await checkFilter("hello", LogicConditions.EQUAL, "no", false) |
|||
}) |
|||
|
|||
it("should be able to test greater than", async () => { |
|||
await checkFilter(10, LogicConditions.GREATER_THAN, 5, true) |
|||
await checkFilter(10, LogicConditions.GREATER_THAN, 15, false) |
|||
}) |
|||
|
|||
it("should be able to test less than", async () => { |
|||
await checkFilter(5, LogicConditions.LESS_THAN, 10, true) |
|||
await checkFilter(15, LogicConditions.LESS_THAN, 10, false) |
|||
}) |
|||
|
|||
it("should be able to in-equality", async () => { |
|||
await checkFilter("hello", LogicConditions.NOT_EQUAL, "no", true) |
|||
await checkFilter(10, LogicConditions.NOT_EQUAL, 10, false) |
|||
}) |
|||
|
|||
it("check number coercion", async () => { |
|||
await checkFilter("10", LogicConditions.GREATER_THAN, "5", true) |
|||
}) |
|||
|
|||
it("check date coercion", async () => { |
|||
await checkFilter( |
|||
(new Date()).toISOString(), |
|||
LogicConditions.GREATER_THAN, |
|||
(new Date(-10000)).toISOString(), |
|||
true |
|||
) |
|||
}) |
|||
|
|||
it("check objects always false", async () => { |
|||
await checkFilter({}, LogicConditions.EQUAL, {}, false) |
|||
}) |
|||
}) |
|||
@ -0,0 +1,39 @@ |
|||
const setup = require("./utilities") |
|||
const fetch = require("node-fetch") |
|||
|
|||
jest.mock("node-fetch") |
|||
|
|||
describe("test the outgoing webhook action", () => { |
|||
let inputs |
|||
let config = setup.getConfig() |
|||
|
|||
beforeEach(async () => { |
|||
await config.init() |
|||
inputs = { |
|||
requestMethod: "POST", |
|||
url: "www.test.com", |
|||
requestBody: JSON.stringify({ |
|||
a: 1, |
|||
}), |
|||
} |
|||
}) |
|||
|
|||
afterAll(setup.afterAll) |
|||
|
|||
it("should be able to run the action", async () => { |
|||
const res = await setup.runStep(setup.actions.OUTGOING_WEBHOOK.stepId, inputs) |
|||
expect(res.success).toEqual(true) |
|||
expect(res.response.url).toEqual("http://www.test.com") |
|||
expect(res.response.method).toEqual("POST") |
|||
expect(res.response.body.a).toEqual(1) |
|||
}) |
|||
|
|||
it("should return an error if something goes wrong in fetch", async () => { |
|||
const res = await setup.runStep(setup.actions.OUTGOING_WEBHOOK.stepId, { |
|||
requestMethod: "GET", |
|||
url: "www.invalid.com" |
|||
}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
|
|||
}) |
|||
@ -0,0 +1,36 @@ |
|||
const setup = require("./utilities") |
|||
|
|||
jest.mock("@sendgrid/mail") |
|||
|
|||
describe("test the send email action", () => { |
|||
let inputs |
|||
let config = setup.getConfig() |
|||
|
|||
beforeEach(async () => { |
|||
await config.init() |
|||
inputs = { |
|||
to: "me@test.com", |
|||
from: "budibase@test.com", |
|||
subject: "Testing", |
|||
text: "Email contents", |
|||
} |
|||
}) |
|||
|
|||
afterAll(setup.afterAll) |
|||
|
|||
it("should be able to run the action", async () => { |
|||
const res = await setup.runStep(setup.actions.SEND_EMAIL.stepId, inputs) |
|||
expect(res.success).toEqual(true) |
|||
// the mocked module throws back the input
|
|||
expect(res.response.to).toEqual("me@test.com") |
|||
}) |
|||
|
|||
it("should return an error if input an invalid email address", async () => { |
|||
const res = await setup.runStep(setup.actions.SEND_EMAIL.stepId, { |
|||
...inputs, |
|||
to: "invalid@test.com", |
|||
}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
|
|||
}) |
|||
@ -0,0 +1,45 @@ |
|||
const env = require("../../environment") |
|||
const setup = require("./utilities") |
|||
|
|||
describe("test the update row action", () => { |
|||
let table, row, inputs |
|||
let config = setup.getConfig() |
|||
|
|||
beforeEach(async () => { |
|||
await config.init() |
|||
table = await config.createTable() |
|||
row = await config.createRow() |
|||
inputs = { |
|||
rowId: row._id, |
|||
row: { |
|||
...row, |
|||
name: "Updated name", |
|||
// put a falsy option in to be removed
|
|||
description: "", |
|||
} |
|||
} |
|||
}) |
|||
|
|||
afterAll(setup.afterAll) |
|||
|
|||
it("should be able to run the action", async () => { |
|||
const res = await setup.runStep(setup.actions.UPDATE_ROW.stepId, inputs) |
|||
expect(res.success).toEqual(true) |
|||
const updatedRow = await config.getRow(table._id, res.id) |
|||
expect(updatedRow.name).toEqual("Updated name") |
|||
expect(updatedRow.description).not.toEqual("") |
|||
}) |
|||
|
|||
it("should check invalid inputs return an error", async () => { |
|||
const res = await setup.runStep(setup.actions.UPDATE_ROW.stepId, {}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
|
|||
it("should return an error when table doesn't exist", async () => { |
|||
const res = await setup.runStep(setup.actions.UPDATE_ROW.stepId, { |
|||
row: { _id: "invalid" }, |
|||
rowId: "invalid", |
|||
}) |
|||
expect(res.success).toEqual(false) |
|||
}) |
|||
}) |
|||
@ -0,0 +1,43 @@ |
|||
const TestConfig = require("../../../tests/utilities/TestConfiguration") |
|||
const actions = require("../../actions") |
|||
const logic = require("../../logic") |
|||
const emitter = require("../../../events/index") |
|||
|
|||
let config |
|||
|
|||
exports.getConfig = () => { |
|||
if (!config) { |
|||
config = new TestConfig(false) |
|||
} |
|||
return config |
|||
} |
|||
|
|||
exports.afterAll = () => { |
|||
config.end() |
|||
} |
|||
|
|||
exports.runStep = async function runStep(stepId, inputs) { |
|||
let step |
|||
if ( |
|||
Object.values(exports.actions) |
|||
.map(action => action.stepId) |
|||
.includes(stepId) |
|||
) { |
|||
step = await actions.getAction(stepId) |
|||
} else { |
|||
step = logic.getLogic(stepId) |
|||
} |
|||
expect(step).toBeDefined() |
|||
return step({ |
|||
inputs, |
|||
appId: config ? config.getAppId() : null, |
|||
// don't really need an API key, mocked out usage quota, not being tested here
|
|||
apiKey: exports.apiKey, |
|||
emitter, |
|||
}) |
|||
} |
|||
|
|||
exports.apiKey = "test" |
|||
|
|||
exports.actions = actions.BUILTIN_DEFINITIONS |
|||
exports.logic = logic.BUILTIN_DEFINITIONS |
|||
@ -1,7 +0,0 @@ |
|||
### Self hosting |
|||
This directory contains utilities that are needed for self hosted platforms to operate. |
|||
These will mostly be utilities, necessary to the operation of the server e.g. storing self |
|||
hosting specific options and attributes to CouchDB. |
|||
|
|||
All the internal operations should be exposed through the `index.js` so importing |
|||
the self host directory should give you everything you need. |
|||
@ -1,44 +0,0 @@ |
|||
const CouchDB = require("../db") |
|||
const env = require("../environment") |
|||
const newid = require("../db/newid") |
|||
|
|||
const SELF_HOST_DB = "self-host-db" |
|||
const SELF_HOST_DOC = "self-host-info" |
|||
|
|||
async function createSelfHostDB(db) { |
|||
await db.put({ |
|||
_id: "_design/database", |
|||
views: {}, |
|||
}) |
|||
const selfHostInfo = { |
|||
_id: SELF_HOST_DOC, |
|||
apiKeyId: newid(), |
|||
} |
|||
await db.put(selfHostInfo) |
|||
return selfHostInfo |
|||
} |
|||
|
|||
exports.init = async () => { |
|||
if (!env.SELF_HOSTED) { |
|||
return |
|||
} |
|||
const db = new CouchDB(SELF_HOST_DB) |
|||
try { |
|||
await db.get(SELF_HOST_DOC) |
|||
} catch (err) { |
|||
// failed to retrieve
|
|||
if (err.status === 404) { |
|||
await createSelfHostDB(db) |
|||
} |
|||
} |
|||
} |
|||
|
|||
exports.getSelfHostInfo = async () => { |
|||
const db = new CouchDB(SELF_HOST_DB) |
|||
return db.get(SELF_HOST_DOC) |
|||
} |
|||
|
|||
exports.getSelfHostAPIKey = async () => { |
|||
const info = await exports.getSelfHostInfo() |
|||
return info ? info.apiKeyId : null |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
module.exports = { |
|||
table: require("../../api/controllers/table"), |
|||
row: require("../../api/controllers/row"), |
|||
role: require("../../api/controllers/role"), |
|||
perms: require("../../api/controllers/permission"), |
|||
view: require("../../api/controllers/view"), |
|||
app: require("../../api/controllers/application"), |
|||
user: require("../../api/controllers/user"), |
|||
automation: require("../../api/controllers/automation"), |
|||
datasource: require("../../api/controllers/datasource"), |
|||
query: require("../../api/controllers/query"), |
|||
screen: require("../../api/controllers/screen"), |
|||
webhook: require("../../api/controllers/webhook"), |
|||
layout: require("../../api/controllers/layout"), |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
exports.makePartial = obj => { |
|||
const newObj = {} |
|||
for (let key of Object.keys(obj)) { |
|||
if (typeof obj[key] === "object") { |
|||
newObj[key] = exports.makePartial(obj[key]) |
|||
} else { |
|||
newObj[key] = obj[key] |
|||
} |
|||
} |
|||
return expect.objectContaining(newObj) |
|||
} |
|||
@ -1,9 +1,9 @@ |
|||
const { BUILTIN_ROLE_IDS } = require("../../../../utilities/security/roles") |
|||
const { BUILTIN_ROLE_IDS } = require("../../utilities/security/roles") |
|||
const { |
|||
BUILTIN_PERMISSION_IDS, |
|||
} = require("../../../../utilities/security/permissions") |
|||
const { createHomeScreen } = require("../../../../constants/screens") |
|||
const { EMPTY_LAYOUT } = require("../../../../constants/layouts") |
|||
} = require("../../utilities/security/permissions") |
|||
const { createHomeScreen } = require("../../constants/screens") |
|||
const { EMPTY_LAYOUT } = require("../../constants/layouts") |
|||
const { cloneDeep } = require("lodash/fp") |
|||
|
|||
exports.basicTable = () => { |
|||
@ -1,16 +0,0 @@ |
|||
const statusCodes = require("./statusCodes") |
|||
|
|||
const errorWithStatus = (message, statusCode) => { |
|||
const e = new Error(message) |
|||
e.statusCode = statusCode |
|||
return e |
|||
} |
|||
|
|||
module.exports.unauthorized = message => |
|||
errorWithStatus(message, statusCodes.UNAUTHORIZED) |
|||
|
|||
module.exports.forbidden = message => |
|||
errorWithStatus(message, statusCodes.FORBIDDEN) |
|||
|
|||
module.exports.notfound = message => |
|||
errorWithStatus(message, statusCodes.NOT_FOUND) |
|||
Loading…
Reference in new issue