forked from tsai/budibase
103 changed files with 905 additions and 1368 deletions
|
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 196 B |
@ -1,3 +1,3 @@ |
|||||
import { flow } from "lodash/fp"; |
import { flow } from "lodash/fp" |
||||
|
|
||||
export const pipe = (arg, funcs) => flow(funcs)(arg) |
export const pipe = (arg, funcs) => flow(funcs)(arg) |
||||
|
|||||
@ -1,21 +1,18 @@ |
|||||
import { eventHandlers } from "../../../../client/src/state/eventHandlers" |
import { eventHandlers } from "../../../../client/src/state/eventHandlers" |
||||
import { writable } from "svelte/store" |
import { writable } from "svelte/store" |
||||
export { EVENT_TYPE_MEMBER_NAME } from "../../../../client/src/state/eventHandlers" |
export { EVENT_TYPE_MEMBER_NAME } from "../../../../client/src/state/eventHandlers" |
||||
import { createCoreApi } from "../../../../client/src/core" |
|
||||
|
|
||||
export const allHandlers = (appDefinition, user) => { |
export const allHandlers = user => { |
||||
const coreApi = createCoreApi(appDefinition, user) |
|
||||
appDefinition.hierarchy = coreApi.templateApi.constructHierarchy( |
|
||||
appDefinition.hierarchy |
|
||||
) |
|
||||
const store = writable({ |
const store = writable({ |
||||
_bbuser: user, |
_bbuser: user, |
||||
}) |
}) |
||||
|
|
||||
const handlersObj = eventHandlers(store, coreApi) |
const handlersObj = eventHandlers(store) |
||||
const handlersArray = [] |
|
||||
for (let key in handlersObj) { |
const handlers = Object.keys(handlersObj).map(name => ({ |
||||
handlersArray.push({ name: key, ...handlersObj[key] }) |
name, |
||||
} |
...handlersObj[name], |
||||
return handlersArray |
})) |
||||
|
|
||||
|
return handlers |
||||
} |
} |
||||
|
|||||
@ -1 +1 @@ |
|||||
export { default } from "./CurrentItemPreview.svelte"; |
export { default } from "./CurrentItemPreview.svelte" |
||||
|
|||||
@ -1,99 +1,23 @@ |
|||||
import { |
|
||||
isString, |
|
||||
isBoolean, |
|
||||
isNumber, |
|
||||
isArray, |
|
||||
isPlainObject, |
|
||||
every, |
|
||||
} from "lodash/fp" |
|
||||
|
|
||||
import { EVENT_TYPE_MEMBER_NAME } from "../../common/eventHandlers" |
|
||||
|
|
||||
import { |
|
||||
isBound, |
|
||||
BB_STATE_BINDINGPATH, |
|
||||
} from "@budibase/client/src/state/parseBinding" |
|
||||
|
|
||||
// const defaultDef = typeName => () => ({
|
|
||||
// type: typeName,
|
|
||||
// required: false,
|
|
||||
// default: types[typeName].default,
|
|
||||
// options: typeName === "options" ? [] : undefined,
|
|
||||
// })
|
|
||||
|
|
||||
// const propType = (defaultValue, isOfType, defaultDefinition) => ({
|
|
||||
// isOfType,
|
|
||||
// default: defaultValue,
|
|
||||
// defaultDefinition,
|
|
||||
// })
|
|
||||
|
|
||||
// const expandSingleProp = propDef => {
|
|
||||
// const p = isString(propDef) ? types[propDef].defaultDefinition() : propDef
|
|
||||
|
|
||||
// if (!isString(propDef)) {
|
|
||||
// const def = types[propDef.type].defaultDefinition()
|
|
||||
// for (let p in def) {
|
|
||||
// if (propDef[p] === undefined) {
|
|
||||
// propDef[p] = def[p]
|
|
||||
// }
|
|
||||
// }
|
|
||||
// }
|
|
||||
|
|
||||
// return p
|
|
||||
// }
|
|
||||
|
|
||||
// export const expandComponentDefinition = componentDefinition => {
|
|
||||
// const expandedProps = {}
|
|
||||
// const expandedComponent = { ...componentDefinition }
|
|
||||
|
|
||||
// for (let p in componentDefinition.props) {
|
|
||||
// expandedProps[p] = expandSingleProp(componentDefinition.props[p])
|
|
||||
// }
|
|
||||
|
|
||||
// expandedComponent.props = expandedProps
|
|
||||
|
|
||||
// if (expandedComponent.children !== false) {
|
|
||||
// expandedComponent.children = true
|
|
||||
// }
|
|
||||
|
|
||||
// return expandedComponent
|
|
||||
// }
|
|
||||
|
|
||||
// const isEvent = e =>
|
|
||||
// isPlainObject(e) &&
|
|
||||
// isString(e[EVENT_TYPE_MEMBER_NAME]) &&
|
|
||||
// isPlainObject(e.parameters)
|
|
||||
|
|
||||
// const isEventList = e => isArray(e) && every(isEvent)(e)
|
|
||||
|
|
||||
// const EMPTY_STATE = () => ({ [BB_STATE_BINDINGPATH]: "" });
|
|
||||
|
|
||||
// export const types = {
|
|
||||
// string: propType("", isString, defaultDef("string")),
|
|
||||
// bool: propType(false, isBoolean, defaultDef("bool")),
|
|
||||
// number: propType(0, isNumber, defaultDef("number")),
|
|
||||
// options: propType("", isString, defaultDef("options")),
|
|
||||
// asset: propType("", isString, defaultDef("asset")),
|
|
||||
// event: propType([], isEventList, defaultDef("event")),
|
|
||||
// // state: propType(EMPTY_STATE, isBound, defaultDef("state")),
|
|
||||
// }
|
|
||||
|
|
||||
|
|
||||
export const TYPE_MAP = { |
export const TYPE_MAP = { |
||||
string: { |
string: { |
||||
default: "" |
default: "", |
||||
}, |
}, |
||||
bool: { |
bool: { |
||||
default: false |
default: false, |
||||
}, |
}, |
||||
number: { |
number: { |
||||
default: 0 |
default: 0, |
||||
}, |
}, |
||||
options: { |
options: { |
||||
default: [], |
default: [], |
||||
options: [] |
options: [], |
||||
}, |
}, |
||||
event: { |
event: { |
||||
default: [], |
default: [], |
||||
} |
}, |
||||
}; |
state: { |
||||
|
default: { |
||||
|
"##bbstate": "", |
||||
|
}, |
||||
|
}, |
||||
|
} |
||||
|
|||||
@ -0,0 +1,4 @@ |
|||||
|
<script> |
||||
|
import { goto } from "@sveltech/routify" |
||||
|
$goto("../page-layout") |
||||
|
</script> |
||||
@ -1,42 +0,0 @@ |
|||||
import { componentDependencies } from "../src/components/userInterface/pagesParsing/findDependencies" |
|
||||
import { componentsAndScreens } from "./testData" |
|
||||
import { some, find } from "lodash/fp" |
|
||||
|
|
||||
describe("component dependencies", () => { |
|
||||
const contains = (result, name) => some(c => c.name === name)(result) |
|
||||
|
|
||||
const get = (all, name) => find(c => c.name === name)(all) |
|
||||
|
|
||||
it("should include component that inheirts", () => { |
|
||||
const { components, screens } = componentsAndScreens() |
|
||||
|
|
||||
const result = componentDependencies( |
|
||||
{}, |
|
||||
screens, |
|
||||
components, |
|
||||
get([...components, ...screens], "budibase-components/TextBox") |
|
||||
) |
|
||||
|
|
||||
expect(contains(result.dependantComponents, "common/SmallTextbox")).toBe( |
|
||||
true |
|
||||
) |
|
||||
}) |
|
||||
|
|
||||
it("should include components in page apbody", () => { |
|
||||
const { components, screens } = componentsAndScreens() |
|
||||
const pages = { |
|
||||
main: { |
|
||||
appBody: "PrimaryButton", |
|
||||
}, |
|
||||
} |
|
||||
|
|
||||
const result = componentDependencies( |
|
||||
pages, |
|
||||
screens, |
|
||||
components, |
|
||||
get([...components, ...screens], "PrimaryButton") |
|
||||
) |
|
||||
|
|
||||
expect(result.dependantPages).toEqual(["main"]) |
|
||||
}) |
|
||||
}) |
|
||||
@ -1,45 +0,0 @@ |
|||||
import { expandComponentDefinition } from "../src/components/userInterface/pagesParsing/types" |
|
||||
|
|
||||
const componentDef = () => ({ |
|
||||
name: "comp", |
|
||||
props: { |
|
||||
label: "string", |
|
||||
width: { type: "number" }, |
|
||||
color: { type: "string", required: true }, |
|
||||
}, |
|
||||
}) |
|
||||
|
|
||||
describe("expandPropDefintion", () => { |
|
||||
it("should expand property defined as string, into default for that type", () => { |
|
||||
const result = expandComponentDefinition(componentDef()) |
|
||||
|
|
||||
expect(result.props.label.type).toBe("string") |
|
||||
expect(result.props.label.required).toBe(false) |
|
||||
}) |
|
||||
|
|
||||
it("should add members to property defined as object, when members do not exist", () => { |
|
||||
const result = expandComponentDefinition(componentDef()) |
|
||||
expect(result.props.width.required).toBe(false) |
|
||||
}) |
|
||||
|
|
||||
it("should not override existing memebers", () => { |
|
||||
const result = expandComponentDefinition(componentDef()) |
|
||||
expect(result.props.color.required).toBe(true) |
|
||||
}) |
|
||||
|
|
||||
it("should set children=true when not included", () => { |
|
||||
const result = expandComponentDefinition(componentDef()) |
|
||||
expect(result.children).toBe(true) |
|
||||
}) |
|
||||
|
|
||||
it("should not change children when specified", () => { |
|
||||
const c = componentDef() |
|
||||
c.children = false |
|
||||
const result = expandComponentDefinition(c) |
|
||||
expect(result.children).toBe(false) |
|
||||
|
|
||||
c.children = true |
|
||||
const result2 = expandComponentDefinition(c) |
|
||||
expect(result2.children).toBe(true) |
|
||||
}) |
|
||||
}) |
|
||||
@ -1,30 +0,0 @@ |
|||||
import { getNewScreen } from "../src/components/userInterface/pagesParsing/createProps" |
|
||||
import { componentsAndScreens, stripStandardProps } from "./testData" |
|
||||
|
|
||||
describe("geNewScreen", () => { |
|
||||
it("should return correct props for screen", () => { |
|
||||
const { components } = componentsAndScreens() |
|
||||
const result = getNewScreen( |
|
||||
components, |
|
||||
"budibase-components/TextBox", |
|
||||
"newscreen" |
|
||||
) |
|
||||
|
|
||||
expect(result.props._code).toBeDefined() |
|
||||
expect(result.props._id).toBeDefined() |
|
||||
expect(result.props._styles).toBeDefined() |
|
||||
stripStandardProps(result.props) |
|
||||
|
|
||||
const expectedProps = { |
|
||||
_component: "budibase-components/TextBox", |
|
||||
size: "", |
|
||||
isPassword: false, |
|
||||
placeholder: "", |
|
||||
label: "", |
|
||||
} |
|
||||
|
|
||||
expect(result.props).toEqual(expectedProps) |
|
||||
expect(result.name).toBe("newscreen") |
|
||||
expect(result.url).toBeDefined() |
|
||||
}) |
|
||||
}) |
|
||||
@ -1 +0,0 @@ |
|||||
export { $ } from "../../../core/src/common" |
|
||||
@ -1,12 +0,0 @@ |
|||||
export const createCoreApp = (backendDefinition, user) => { |
|
||||
const app = { |
|
||||
datastore: null, |
|
||||
crypto: null, |
|
||||
publish: () => {}, |
|
||||
hierarchy: backendDefinition.hierarchy, |
|
||||
actions: backendDefinition.actions, |
|
||||
user, |
|
||||
} |
|
||||
|
|
||||
return app |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
import { createCoreApp } from "./createCoreApp" |
|
||||
import { getNew, getNewChild } from "../../../core/src/recordApi/getNew" |
|
||||
import { constructHierarchy } from "../../../core/src/templateApi/createNodes" |
|
||||
|
|
||||
export const createCoreApi = (backendDefinition, user) => { |
|
||||
const app = createCoreApp(backendDefinition, user) |
|
||||
|
|
||||
return { |
|
||||
recordApi: { |
|
||||
getNew: getNew(app), |
|
||||
getNewChild: getNewChild(app), |
|
||||
}, |
|
||||
|
|
||||
templateApi: { |
|
||||
constructHierarchy, |
|
||||
}, |
|
||||
} |
|
||||
} |
|
||||
@ -1,40 +1,38 @@ |
|||||
const CouchDB = require("../../db"); |
const CouchDB = require("../../db") |
||||
const { |
const { getPackageForBuilder } = require("../../utilities/builder") |
||||
getPackageForBuilder, |
|
||||
} = require("../../utilities/builder") |
|
||||
|
|
||||
exports.fetch = async function(ctx) { |
exports.fetch = async function(ctx) { |
||||
const clientDb = new CouchDB(`client-${ctx.params.clientId}`); |
const clientDb = new CouchDB(`client-${ctx.params.clientId}`) |
||||
const body = await clientDb.query("client/by_type", { |
const body = await clientDb.query("client/by_type", { |
||||
include_docs: true, |
include_docs: true, |
||||
key: ["app"] |
key: ["app"], |
||||
}); |
}) |
||||
|
|
||||
ctx.body = body.rows.map(row => row.doc); |
ctx.body = body.rows.map(row => row.doc) |
||||
}; |
} |
||||
|
|
||||
exports.fetchAppPackage = async function(ctx) { |
exports.fetchAppPackage = async function(ctx) { |
||||
const clientDb = new CouchDB(`client-${ctx.params.clientId}`); |
const clientDb = new CouchDB(`client-${ctx.params.clientId}`) |
||||
const application = await clientDb.get(ctx.params.applicationId); |
const application = await clientDb.get(ctx.params.applicationId) |
||||
ctx.body = await getPackageForBuilder(ctx.config, application); |
ctx.body = await getPackageForBuilder(ctx.config, application) |
||||
} |
} |
||||
|
|
||||
exports.create = async function(ctx) { |
exports.create = async function(ctx) { |
||||
const clientDb = new CouchDB(`client-${ctx.params.clientId}`); |
const clientDb = new CouchDB(`client-${ctx.params.clientId}`) |
||||
const { id, rev } = await clientDb.post({ |
const { id, rev } = await clientDb.post({ |
||||
type: "app", |
type: "app", |
||||
instances: [], |
instances: [], |
||||
userInstanceMap: {}, |
userInstanceMap: {}, |
||||
componentLibraries: [ |
componentLibraries: [ |
||||
"@budibase/standard-components", |
"@budibase/standard-components", |
||||
"@budibase/materialdesign-components" |
"@budibase/materialdesign-components", |
||||
], |
], |
||||
...ctx.request.body, |
...ctx.request.body, |
||||
}); |
}) |
||||
|
|
||||
ctx.body = { |
ctx.body = { |
||||
id, |
id, |
||||
rev, |
rev, |
||||
message: `Application ${ctx.request.body.name} created successfully` |
message: `Application ${ctx.request.body.name} created successfully`, |
||||
} |
} |
||||
}; |
} |
||||
|
|||||
@ -1,56 +1,57 @@ |
|||||
const jwt = require("jsonwebtoken"); |
const jwt = require("jsonwebtoken") |
||||
const CouchDB = require("../../db"); |
const CouchDB = require("../../db") |
||||
const bcrypt = require("../../utilities/bcrypt"); |
const bcrypt = require("../../utilities/bcrypt") |
||||
|
|
||||
exports.authenticate = async ctx => { |
exports.authenticate = async ctx => { |
||||
const { username, password } = ctx.request.body; |
const { username, password } = ctx.request.body |
||||
|
|
||||
if (!username) ctx.throw(400, "Username Required."); |
if (!username) ctx.throw(400, "Username Required.") |
||||
if (!password) ctx.throw(400, "Password Required"); |
if (!password) ctx.throw(400, "Password Required") |
||||
|
|
||||
// TODO: Don't use this. It can't be relied on
|
// TODO: Don't use this. It can't be relied on
|
||||
const referer = ctx.request.headers.referer.split("/"); |
const referer = ctx.request.headers.referer.split("/") |
||||
const appId = referer[3]; |
const appId = referer[3] |
||||
|
|
||||
// find the instance that the user is associated with
|
// find the instance that the user is associated with
|
||||
const db = new CouchDB(`client-${process.env.CLIENT_ID}`); |
const db = new CouchDB(`client-${process.env.CLIENT_ID}`) |
||||
const app = await db.get(appId); |
const app = await db.get(appId) |
||||
const instanceId = app.userInstanceMap[username]; |
const instanceId = app.userInstanceMap[username] |
||||
|
|
||||
if (!instanceId) ctx.throw(500, "User is not associated with an instance of app", appId) |
if (!instanceId) |
||||
|
ctx.throw(500, "User is not associated with an instance of app", appId) |
||||
|
|
||||
// Check the user exists in the instance DB by username
|
// Check the user exists in the instance DB by username
|
||||
const instanceDb = new CouchDB(instanceId); |
const instanceDb = new CouchDB(instanceId) |
||||
const { rows } = await instanceDb.query("database/by_username", { |
const { rows } = await instanceDb.query("database/by_username", { |
||||
include_docs: true, |
include_docs: true, |
||||
username |
username, |
||||
}); |
}) |
||||
|
|
||||
if (rows.length === 0) ctx.throw(500, `User does not exist.`); |
if (rows.length === 0) ctx.throw(500, `User does not exist.`) |
||||
|
|
||||
const dbUser = rows[0].doc; |
const dbUser = rows[0].doc |
||||
|
|
||||
// authenticate
|
// authenticate
|
||||
if (await bcrypt.compare(password, dbUser.password)) { |
if (await bcrypt.compare(password, dbUser.password)) { |
||||
const payload = { |
const payload = { |
||||
userId: dbUser._id, |
userId: dbUser._id, |
||||
accessLevel: "", |
accessLevel: "", |
||||
instanceId: instanceId |
instanceId: instanceId, |
||||
}; |
} |
||||
|
|
||||
const token = jwt.sign(payload, ctx.config.jwtSecret, { |
const token = jwt.sign(payload, ctx.config.jwtSecret, { |
||||
expiresIn: "1 day" |
expiresIn: "1 day", |
||||
}); |
}) |
||||
|
|
||||
const ONE_DAY_FROM_NOW = new Date(Date.now() + (24 * 3600)) |
const ONE_DAY_FROM_NOW = new Date(Date.now() + 24 * 3600) |
||||
|
|
||||
ctx.cookies.set('budibase:token', token, { expires: ONE_DAY_FROM_NOW }); |
ctx.cookies.set("budibase:token", token, { expires: ONE_DAY_FROM_NOW }) |
||||
|
|
||||
ctx.body = { |
ctx.body = { |
||||
token, |
token, |
||||
...dbUser |
...dbUser, |
||||
}; |
} |
||||
} else { |
} else { |
||||
ctx.throw(401, "Invalid credentials."); |
ctx.throw(401, "Invalid credentials.") |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,36 +1,36 @@ |
|||||
const CouchDB = require("../../db"); |
const CouchDB = require("../../db") |
||||
|
|
||||
exports.getClientId = async function(ctx) { |
exports.getClientId = async function(ctx) { |
||||
ctx.body = process.env.CLIENT_ID; |
ctx.body = process.env.CLIENT_ID |
||||
}; |
} |
||||
|
|
||||
exports.create = async function(ctx) { |
exports.create = async function(ctx) { |
||||
const clientId = `client-${ctx.request.body.clientId}`; |
const clientId = `client-${ctx.request.body.clientId}` |
||||
const db = new CouchDB(clientId); |
const db = new CouchDB(clientId) |
||||
|
|
||||
await db.put({ |
await db.put({ |
||||
_id: "_design/client", |
_id: "_design/client", |
||||
views: { |
views: { |
||||
by_type: { |
by_type: { |
||||
map: function(doc) { |
map: function(doc) { |
||||
emit([doc.type], doc._id); |
emit([doc.type], doc._id) |
||||
}.toString() |
}.toString(), |
||||
} |
}, |
||||
} |
}, |
||||
}); |
}) |
||||
|
|
||||
ctx.body = { |
ctx.body = { |
||||
message: `Client Database ${clientId} successfully provisioned.` |
message: `Client Database ${clientId} successfully provisioned.`, |
||||
} |
} |
||||
}; |
} |
||||
|
|
||||
exports.destroy = async function(ctx) { |
exports.destroy = async function(ctx) { |
||||
const dbId = `client-${ctx.params.clientId}`; |
const dbId = `client-${ctx.params.clientId}` |
||||
|
|
||||
await new CouchDB(dbId).destroy(); |
await new CouchDB(dbId).destroy() |
||||
|
|
||||
ctx.body = { |
ctx.body = { |
||||
status: 200, |
status: 200, |
||||
message: `Client Database ${dbId} successfully deleted.` |
message: `Client Database ${dbId} successfully deleted.`, |
||||
} |
} |
||||
}; |
} |
||||
|
|||||
@ -1,40 +1,51 @@ |
|||||
const CouchDB = require("../../db"); |
const CouchDB = require("../../db") |
||||
const { homedir } = require("os"); |
const { homedir } = require("os") |
||||
const { resolve, join } = require("path"); |
const { resolve, join } = require("path") |
||||
|
|
||||
const isDev = process.env.NODE_ENV !== "production"; |
const isDev = process.env.NODE_ENV !== "production" |
||||
|
|
||||
exports.fetchAppComponentDefinitions = async function(ctx) { |
exports.fetchAppComponentDefinitions = async function(ctx) { |
||||
const db = new CouchDB(`client-${ctx.params.clientId}`); |
const db = new CouchDB(`client-${ctx.params.clientId}`) |
||||
const app = await db.get(ctx.params.appId) |
const app = await db.get(ctx.params.appId) |
||||
|
|
||||
const componentDefinitions = app.componentLibraries.reduce((acc, componentLibrary) => { |
const componentDefinitions = app.componentLibraries.reduce( |
||||
|
(acc, componentLibrary) => { |
||||
let appDirectory = resolve(homedir(), ".budibase", ctx.params.appId, "node_modules"); |
let appDirectory = resolve( |
||||
|
homedir(), |
||||
if (isDev) { |
".budibase", |
||||
appDirectory = "/tmp/.budibase"; |
ctx.params.appId, |
||||
} |
"node_modules" |
||||
|
) |
||||
const componentJson = require(join(appDirectory, componentLibrary, "components.json")); |
|
||||
|
if (isDev) { |
||||
const result = {}; |
appDirectory = "/tmp/.budibase" |
||||
|
} |
||||
// map over the components.json and add the library identifier as a key
|
|
||||
// button -> @budibase/standard-components/button
|
const componentJson = require(join( |
||||
for (key in componentJson) { |
appDirectory, |
||||
const fullComponentName = `${componentLibrary}/${key}`; |
componentLibrary, |
||||
result[fullComponentName] = { |
"components.json" |
||||
_component: fullComponentName, |
)) |
||||
...componentJson[key] |
|
||||
} |
const result = {} |
||||
} |
|
||||
|
// map over the components.json and add the library identifier as a key
|
||||
return { |
// button -> @budibase/standard-components/button
|
||||
...acc, |
for (key in componentJson) { |
||||
...result |
const fullComponentName = `${componentLibrary}/${key}` |
||||
}; |
result[fullComponentName] = { |
||||
}, {}); |
_component: fullComponentName, |
||||
|
...componentJson[key], |
||||
ctx.body = componentDefinitions; |
} |
||||
}; |
} |
||||
|
|
||||
|
return { |
||||
|
...acc, |
||||
|
...result, |
||||
|
} |
||||
|
}, |
||||
|
{} |
||||
|
) |
||||
|
|
||||
|
ctx.body = componentDefinitions |
||||
|
} |
||||
|
|||||
@ -1,61 +1,63 @@ |
|||||
const CouchDB = require("../../db"); |
const CouchDB = require("../../db") |
||||
|
|
||||
exports.create = async function(ctx) { |
exports.create = async function(ctx) { |
||||
const instanceName = ctx.request.body.name; |
const instanceName = ctx.request.body.name |
||||
|
|
||||
const { clientId, applicationId } = ctx.params; |
const { clientId, applicationId } = ctx.params |
||||
const db = new CouchDB(instanceName); |
const db = new CouchDB(instanceName) |
||||
await db.put({ |
await db.put({ |
||||
_id: "_design/database", |
_id: "_design/database", |
||||
metadata: { |
metadata: { |
||||
clientId, |
clientId, |
||||
applicationId |
applicationId, |
||||
}, |
}, |
||||
views: { |
views: { |
||||
by_username: { |
by_username: { |
||||
map: function(doc) { |
map: function(doc) { |
||||
if (doc.type === "user") { |
if (doc.type === "user") { |
||||
emit([doc.username], doc._id); |
emit([doc.username], doc._id) |
||||
} |
} |
||||
}.toString() |
}.toString(), |
||||
}, |
}, |
||||
by_type: { |
by_type: { |
||||
map: function(doc) { |
map: function(doc) { |
||||
emit([doc.type], doc._id); |
emit([doc.type], doc._id) |
||||
}.toString() |
}.toString(), |
||||
} |
}, |
||||
} |
}, |
||||
}); |
}) |
||||
|
|
||||
// Add the new instance under the app clientDB
|
// Add the new instance under the app clientDB
|
||||
const clientDatabaseId = `client-${clientId}` |
const clientDatabaseId = `client-${clientId}` |
||||
const clientDb = new CouchDB(clientDatabaseId); |
const clientDb = new CouchDB(clientDatabaseId) |
||||
const budibaseApp = await clientDb.get(applicationId); |
const budibaseApp = await clientDb.get(applicationId) |
||||
const instance = { id: instanceName, name: instanceName }; |
const instance = { id: instanceName, name: instanceName } |
||||
budibaseApp.instances.push(instance); |
budibaseApp.instances.push(instance) |
||||
await clientDb.put(budibaseApp); |
await clientDb.put(budibaseApp) |
||||
|
|
||||
ctx.body = { |
ctx.body = { |
||||
message: `Instance Database ${instanceName} successfully provisioned.`, |
message: `Instance Database ${instanceName} successfully provisioned.`, |
||||
status: 200, |
status: 200, |
||||
instance |
instance, |
||||
} |
} |
||||
}; |
} |
||||
|
|
||||
exports.destroy = async function(ctx) { |
exports.destroy = async function(ctx) { |
||||
const db = new CouchDB(ctx.params.instanceId); |
const db = new CouchDB(ctx.params.instanceId) |
||||
const designDoc = await db.get("_design/database"); |
const designDoc = await db.get("_design/database") |
||||
await db.destroy(); |
await db.destroy() |
||||
|
|
||||
// remove instance from client application document
|
// remove instance from client application document
|
||||
const { metadata } = designDoc; |
const { metadata } = designDoc |
||||
const clientDb = new CouchDB(metadata.clientId); |
const clientDb = new CouchDB(metadata.clientId) |
||||
const budibaseApp = await clientDb.get(metadata.applicationId); |
const budibaseApp = await clientDb.get(metadata.applicationId) |
||||
budibaseApp.instances = budibaseApp.instances.filter(instance => instance !== ctx.params.instanceId); |
budibaseApp.instances = budibaseApp.instances.filter( |
||||
const updatedApp = await clientDb.put(budibaseApp); |
instance => instance !== ctx.params.instanceId |
||||
|
) |
||||
|
const updatedApp = await clientDb.put(budibaseApp) |
||||
|
|
||||
ctx.body = { |
ctx.body = { |
||||
message: `Instance Database ${ctx.params.instanceId} successfully destroyed.`, |
message: `Instance Database ${ctx.params.instanceId} successfully destroyed.`, |
||||
status: 200 |
status: 200, |
||||
} |
} |
||||
}; |
} |
||||
|
|||||
@ -1,57 +1,57 @@ |
|||||
const CouchDB = require("../../db"); |
const CouchDB = require("../../db") |
||||
const bcrypt = require("../../utilities/bcrypt"); |
const bcrypt = require("../../utilities/bcrypt") |
||||
|
|
||||
exports.fetch = async function(ctx) { |
exports.fetch = async function(ctx) { |
||||
const database = new CouchDB(ctx.params.instanceId); |
const database = new CouchDB(ctx.params.instanceId) |
||||
const data = await database.query("database/by_type", { |
const data = await database.query("database/by_type", { |
||||
include_docs: true, |
include_docs: true, |
||||
key: ["user"] |
key: ["user"], |
||||
}); |
}) |
||||
|
|
||||
ctx.body = data.rows.map(row => row.doc); |
ctx.body = data.rows.map(row => row.doc) |
||||
}; |
} |
||||
|
|
||||
exports.create = async function(ctx) { |
exports.create = async function(ctx) { |
||||
const database = new CouchDB(ctx.params.instanceId); |
const database = new CouchDB(ctx.params.instanceId) |
||||
const { username, password, name } = ctx.request.body; |
const { username, password, name } = ctx.request.body |
||||
|
|
||||
if (!username || !password) ctx.throw(400, "Username and Password Required."); |
if (!username || !password) ctx.throw(400, "Username and Password Required.") |
||||
|
|
||||
const response = await database.post({ |
const response = await database.post({ |
||||
username, |
username, |
||||
password: await bcrypt.hash(password), |
password: await bcrypt.hash(password), |
||||
name, |
name, |
||||
type: "user" |
type: "user", |
||||
}); |
}) |
||||
|
|
||||
// the clientDB needs to store a map of users against the app
|
// the clientDB needs to store a map of users against the app
|
||||
const clientDb = new CouchDB(`client-${process.env.CLIENT_ID}`); |
const clientDb = new CouchDB(`client-${process.env.CLIENT_ID}`) |
||||
const app = await clientDb.get(ctx.params.appId); |
const app = await clientDb.get(ctx.params.appId) |
||||
|
|
||||
app.userInstanceMap = { |
app.userInstanceMap = { |
||||
...app.userInstanceMap, |
...app.userInstanceMap, |
||||
[username]: ctx.params.instanceId |
[username]: ctx.params.instanceId, |
||||
} |
} |
||||
await clientDb.put(app); |
await clientDb.put(app) |
||||
|
|
||||
ctx.body = { |
ctx.body = { |
||||
user: { |
user: { |
||||
id: response.id, |
id: response.id, |
||||
rev: response.rev, |
rev: response.rev, |
||||
username, |
username, |
||||
name |
name, |
||||
}, |
}, |
||||
message: `User created successfully.`, |
message: `User created successfully.`, |
||||
status: 200 |
status: 200, |
||||
} |
} |
||||
}; |
} |
||||
|
|
||||
exports.destroy = async function(ctx) { |
exports.destroy = async function(ctx) { |
||||
const database = new CouchDB(ctx.params.instanceId); |
const database = new CouchDB(ctx.params.instanceId) |
||||
const response = await database.destroy(ctx.params.userId) |
const response = await database.destroy(ctx.params.userId) |
||||
ctx.body = { |
ctx.body = { |
||||
...response, |
...response, |
||||
message: `User deleted.`, |
message: `User deleted.`, |
||||
status: 200 |
status: 200, |
||||
} |
} |
||||
}; |
} |
||||
|
|||||
@ -1,11 +1,11 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/application"); |
const controller = require("../controllers/application") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router |
||||
.get("/api/:clientId/applications", controller.fetch) |
.get("/api/:clientId/applications", controller.fetch) |
||||
.get("/api/:clientId/:applicationId/appPackage", controller.fetchAppPackage) |
.get("/api/:clientId/:applicationId/appPackage", controller.fetchAppPackage) |
||||
.post("/api/:clientId/applications", controller.create); |
.post("/api/:clientId/applications", controller.create) |
||||
|
|
||||
module.exports = router; |
module.exports = router |
||||
|
|||||
@ -1,9 +1,8 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/auth"); |
const controller = require("../controllers/auth") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router.post("/api/authenticate", controller.authenticate) |
||||
.post("/api/authenticate", controller.authenticate); |
|
||||
|
|
||||
module.exports = router; |
module.exports = router |
||||
|
|||||
@ -1,11 +1,11 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/client"); |
const controller = require("../controllers/client") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router |
||||
.get("/api/client/id", controller.getClientId) |
.get("/api/client/id", controller.getClientId) |
||||
.post("/api/clients", controller.create) |
.post("/api/clients", controller.create) |
||||
.delete("/api/clients/:clientId", controller.destroy); |
.delete("/api/clients/:clientId", controller.destroy) |
||||
|
|
||||
module.exports = router; |
module.exports = router |
||||
|
|||||
@ -1,9 +1,11 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/component"); |
const controller = require("../controllers/component") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router.get( |
||||
.get("/:clientId/:appId/components/definitions", controller.fetchAppComponentDefinitions); |
"/:clientId/:appId/components/definitions", |
||||
|
controller.fetchAppComponentDefinitions |
||||
|
) |
||||
|
|
||||
module.exports = router; |
module.exports = router |
||||
|
|||||
@ -1,10 +1,10 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/instance"); |
const controller = require("../controllers/instance") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router |
||||
.post("/api/:clientId/:applicationId/instances", controller.create) |
.post("/api/:clientId/:applicationId/instances", controller.create) |
||||
.delete("/api/instances/:instanceId", controller.destroy); |
.delete("/api/instances/:instanceId", controller.destroy) |
||||
|
|
||||
module.exports = router; |
module.exports = router |
||||
|
|||||
@ -1,13 +1,12 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/model"); |
const controller = require("../controllers/model") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router |
||||
.get("/api/:instanceId/models", controller.fetch) |
.get("/api/:instanceId/models", controller.fetch) |
||||
.post("/api/:instanceId/models", controller.create) |
.post("/api/:instanceId/models", controller.create) |
||||
// .patch("/api/:instanceId/models", controller.update)
|
// .patch("/api/:instanceId/models", controller.update)
|
||||
.delete("/api/:instanceId/models/:modelId/:revId", controller.destroy); |
.delete("/api/:instanceId/models/:modelId/:revId", controller.destroy) |
||||
|
|
||||
|
module.exports = router |
||||
module.exports = router; |
|
||||
|
|||||
@ -1,12 +1,11 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/screen"); |
const controller = require("../controllers/screen") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router |
||||
.get("/api/:instanceId/screens", controller.fetch) |
.get("/api/:instanceId/screens", controller.fetch) |
||||
.post("/api/:instanceId/screens", controller.save) |
.post("/api/:instanceId/screens", controller.save) |
||||
.delete("/api/:instanceId/:screenId/:revId", controller.destroy); |
.delete("/api/:instanceId/:screenId/:revId", controller.destroy) |
||||
|
|
||||
|
module.exports = router |
||||
module.exports = router; |
|
||||
|
|||||
@ -1,21 +1,21 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/static"); |
const controller = require("../controllers/static") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router |
||||
.param("file", async (file, ctx, next) => { |
.param("file", async (file, ctx, next) => { |
||||
ctx.file = file && file.includes(".") ? file : "index.html"; |
ctx.file = file && file.includes(".") ? file : "index.html" |
||||
|
|
||||
// Serving the client library from your local dir in dev
|
// Serving the client library from your local dir in dev
|
||||
if (ctx.isDev && ctx.file.startsWith("budibase-client")) { |
if (ctx.isDev && ctx.file.startsWith("budibase-client")) { |
||||
ctx.devPath = "/tmp/.budibase"; |
ctx.devPath = "/tmp/.budibase" |
||||
} |
} |
||||
|
|
||||
await next(); |
await next() |
||||
}) |
}) |
||||
.get("/_builder/:file*", controller.serveBuilder) |
.get("/_builder/:file*", controller.serveBuilder) |
||||
.get("/:appId/componentlibrary", controller.serveComponentLibrary) |
.get("/:appId/componentlibrary", controller.serveComponentLibrary) |
||||
.get("/:appId/:file*", controller.serveApp); |
.get("/:appId/:file*", controller.serveApp) |
||||
|
|
||||
module.exports = router; |
module.exports = router |
||||
|
|||||
@ -1,11 +1,11 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/user"); |
const controller = require("../controllers/user") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router |
||||
.get("/api/:instanceId/users", controller.fetch) |
.get("/api/:instanceId/users", controller.fetch) |
||||
.post("/api/:appId/:instanceId/users", controller.create) |
.post("/api/:appId/:instanceId/users", controller.create) |
||||
.delete("/api/:instanceId/users/:userId", controller.destroy); |
.delete("/api/:instanceId/users/:userId", controller.destroy) |
||||
|
|
||||
module.exports = router; |
module.exports = router |
||||
|
|||||
@ -1,12 +1,12 @@ |
|||||
const Router = require("@koa/router"); |
const Router = require("@koa/router") |
||||
const controller = require("../controllers/view"); |
const controller = require("../controllers/view") |
||||
|
|
||||
const router = Router(); |
const router = Router() |
||||
|
|
||||
router |
router |
||||
.get("/api/:instanceId/views", controller.fetch) |
.get("/api/:instanceId/views", controller.fetch) |
||||
// .patch("/api/:databaseId/views", controller.update);
|
// .patch("/api/:databaseId/views", controller.update);
|
||||
// .delete("/api/:instanceId/views/:viewId/:revId", controller.destroy);
|
// .delete("/api/:instanceId/views/:viewId/:revId", controller.destroy);
|
||||
.post("/api/:instanceId/views", controller.create); |
.post("/api/:instanceId/views", controller.create) |
||||
|
|
||||
module.exports = router; |
module.exports = router |
||||
|
|||||
@ -1,17 +1,17 @@ |
|||||
const PouchDB = require("pouchdb") |
const PouchDB = require("pouchdb") |
||||
const allDbs = require("pouchdb-all-dbs") |
const allDbs = require("pouchdb-all-dbs") |
||||
const os = require("os"); |
const os = require("os") |
||||
const path = require("path"); |
const path = require("path") |
||||
|
|
||||
const BUDIBASE_DIR = path.join(os.homedir(), ".budibase"); |
const BUDIBASE_DIR = path.join(os.homedir(), ".budibase") |
||||
|
|
||||
const COUCH_DB_URL = process.env.COUCH_DB_URL || `leveldb://${BUDIBASE_DIR}/`; |
const COUCH_DB_URL = process.env.COUCH_DB_URL || `leveldb://${BUDIBASE_DIR}/` |
||||
const DATABASE_TYPE = process.env.DATABASE_TYPE || "couch"; |
const DATABASE_TYPE = process.env.DATABASE_TYPE || "couch" |
||||
|
|
||||
const Pouch = PouchDB.defaults({ |
const Pouch = PouchDB.defaults({ |
||||
prefix: COUCH_DB_URL, |
prefix: COUCH_DB_URL, |
||||
}); |
}) |
||||
|
|
||||
allDbs(Pouch); |
allDbs(Pouch) |
||||
|
|
||||
module.exports = Pouch; |
module.exports = Pouch |
||||
|
|||||
@ -1,21 +1,21 @@ |
|||||
const jwt = require("jsonwebtoken"); |
const jwt = require("jsonwebtoken") |
||||
|
|
||||
module.exports = async (ctx, next) => { |
module.exports = async (ctx, next) => { |
||||
const token = ctx.cookies.get("budibase:token"); |
const token = ctx.cookies.get("budibase:token") |
||||
console.log("TOKEN", token); |
console.log("TOKEN", token) |
||||
|
|
||||
if (!token) { |
if (!token) { |
||||
ctx.isAuthenticated = false |
ctx.isAuthenticated = false |
||||
await next(); |
await next() |
||||
return; |
return |
||||
}; |
} |
||||
|
|
||||
try { |
try { |
||||
ctx.jwtPayload = jwt.verify(token, ctx.config.jwtSecret); |
ctx.jwtPayload = jwt.verify(token, ctx.config.jwtSecret) |
||||
ctx.isAuthenticated = true; |
ctx.isAuthenticated = true |
||||
} catch (err) { |
} catch (err) { |
||||
ctx.throw(err.status || 403, err.text); |
ctx.throw(err.status || 403, err.text) |
||||
} |
} |
||||
|
|
||||
await next(); |
await next() |
||||
}; |
} |
||||
|
|||||
@ -1,11 +1,12 @@ |
|||||
const bcrypt = require("bcryptjs"); |
const bcrypt = require("bcryptjs") |
||||
|
|
||||
const SALT_ROUNDS = process.env.SALT_ROUNDS || 10; |
const SALT_ROUNDS = process.env.SALT_ROUNDS || 10 |
||||
|
|
||||
exports.hash = async data => { |
exports.hash = async data => { |
||||
const salt = await bcrypt.genSalt(SALT_ROUNDS); |
const salt = await bcrypt.genSalt(SALT_ROUNDS) |
||||
const result = await bcrypt.hash(data, salt); |
const result = await bcrypt.hash(data, salt) |
||||
return result; |
return result |
||||
}; |
} |
||||
|
|
||||
exports.compare = async (data, encrypted) => await bcrypt.compare(data, encrypted); |
exports.compare = async (data, encrypted) => |
||||
|
await bcrypt.compare(data, encrypted) |
||||
|
|||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue