From 8a7c0f8ba3640cbf94ba2617e644553ec65c78d7 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 23 Apr 2020 14:37:08 +0100 Subject: [PATCH] pouchDB integration, use app id instead of app name for keying app packages --- .../builderStore/loadComponentLibraries.js | 16 +- .../builder/src/builderStore/store/backend.js | 265 +++-- .../builder/src/builderStore/store/index.js | 48 +- .../components/database/ModelDataTable/api.js | 19 +- .../modals/CreateDatabase.svelte | 4 +- .../ModelDataTable/modals/CreateUser.svelte | 25 +- .../src/components/nav/DatabasesList.svelte | 2 +- .../src/components/nav/UsersList.svelte | 6 +- .../src/components/start/AppList.svelte | 2 +- .../src/pages/[application]/_layout.svelte | 2 +- packages/builder/src/pages/index.svelte | 3 +- packages/common/.gitignore | 49 +- packages/common/node_modules/fsevents/LICENSE | 22 - .../common/node_modules/fsevents/README.md | 78 -- .../common/node_modules/fsevents/fsevents.js | 106 -- .../common/node_modules/fsevents/package.json | 36 - packages/server/budibase-instance/000005.ldb | Bin 0 -> 629 bytes packages/server/budibase-instance/CURRENT | 1 + packages/server/budibase-instance/LOCK | 0 packages/server/budibase-instance/LOG | 5 + packages/server/budibase-instance/LOG.old | 1 + .../server/budibase-instance/MANIFEST-000004 | Bin 0 -> 129 bytes packages/server/client-budibase/CURRENT | 1 + packages/server/client-budibase/LOCK | 0 packages/server/client-budibase/LOG | 1 + .../server/client-budibase/MANIFEST-000002 | Bin 0 -> 50 bytes packages/server/db/client.js | 9 +- packages/server/middleware/authenticated.js | 15 + .../middleware/controllers/application.js | 12 +- .../server/middleware/controllers/auth.js | 57 +- .../server/middleware/controllers/client.js | 11 +- .../server/middleware/controllers/instance.js | 31 +- .../server/middleware/controllers/model.js | 26 +- .../server/middleware/controllers/record.js | 17 +- .../server/middleware/controllers/user.js | 29 +- .../server/middleware/controllers/view.js | 12 +- packages/server/middleware/routes/apps.js | 14 +- .../middleware/routes/neo/tests/user.spec.js | 1 - packages/server/package.json | 5 +- packages/server/utilities/bcrypt.js | 11 + packages/server/utilities/builder/index.js | 2 +- .../server/utilities/masterAppInternal.js | 1 + packages/server/yarn.lock | 969 ++++++++++++------ 43 files changed, 1017 insertions(+), 897 deletions(-) delete mode 100644 packages/common/node_modules/fsevents/LICENSE delete mode 100644 packages/common/node_modules/fsevents/README.md delete mode 100644 packages/common/node_modules/fsevents/fsevents.js delete mode 100644 packages/common/node_modules/fsevents/package.json create mode 100644 packages/server/budibase-instance/000005.ldb create mode 100644 packages/server/budibase-instance/CURRENT create mode 100644 packages/server/budibase-instance/LOCK create mode 100644 packages/server/budibase-instance/LOG create mode 100644 packages/server/budibase-instance/LOG.old create mode 100644 packages/server/budibase-instance/MANIFEST-000004 create mode 100644 packages/server/client-budibase/CURRENT create mode 100644 packages/server/client-budibase/LOCK create mode 100644 packages/server/client-budibase/LOG create mode 100644 packages/server/client-budibase/MANIFEST-000002 create mode 100644 packages/server/middleware/authenticated.js create mode 100644 packages/server/utilities/bcrypt.js diff --git a/packages/builder/src/builderStore/loadComponentLibraries.js b/packages/builder/src/builderStore/loadComponentLibraries.js index 8534bcf177..8dba9ffe92 100644 --- a/packages/builder/src/builderStore/loadComponentLibraries.js +++ b/packages/builder/src/builderStore/loadComponentLibraries.js @@ -1,34 +1,34 @@ import { flatten, values, uniq, map } from "lodash/fp" import { pipe } from "components/common/core" -export const loadLibs = async (appName, appPackage) => { +export const loadLibs = async (appId, appPackage) => { const allLibraries = {} for (let lib of libsFromPages(appPackage.pages)) { - const libModule = await import(makeLibraryUrl(appName, lib)) + const libModule = await import(makeLibraryUrl(appId, lib)) allLibraries[lib] = libModule } return allLibraries } -export const loadLibUrls = (appName, appPackage) => { +export const loadLibUrls = (appId, appPackage) => { const allLibraries = [] for (let lib of libsFromPages(appPackage.pages)) { - const libUrl = makeLibraryUrl(appName, lib) + const libUrl = makeLibraryUrl(appId, lib) allLibraries.push({ libName: lib, importPath: libUrl }) } return allLibraries } -export const loadLib = async (appName, lib, allLibs) => { - allLibs[lib] = await import(makeLibraryUrl(appName, lib)) +export const loadLib = async (appId, lib, allLibs) => { + allLibs[lib] = await import(makeLibraryUrl(appId, lib)) return allLibs } -export const makeLibraryUrl = (appName, lib) => - `/_builder/${appName}/componentlibrary?lib=${encodeURI(lib)}` +export const makeLibraryUrl = (appId, lib) => + `/_builder/${appId}/componentlibrary?lib=${encodeURI(lib)}` export const libsFromPages = pages => pipe(pages, [values, map(p => p.componentLibraries), flatten, uniq]) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 3005eaf659..7f975e6168 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -1,15 +1,9 @@ import { writable } from "svelte/store" import api from "../api" -import { cloneDeep, sortBy, find, remove } from "lodash/fp" -import { hierarchy as hierarchyFunctions } from "../../../../core/src" +import { find } from "lodash/fp" import { getNode, - validate, constructHierarchy, - templateApi, - isIndex, - canDeleteIndex, - canDeleteModel, } from "components/common/core" export const getBackendUiStore = () => { @@ -20,6 +14,7 @@ export const getBackendUiStore = () => { }, breadcrumbs: [], models: [], + users: [], selectedDatabase: {}, selectedModel: {}, } @@ -103,38 +98,24 @@ export const saveBackend = async state => { }, accessLevels: state.accessLevels, }) - - const instances_currentFirst = state.selectedDatabase - ? [ - state.appInstances.find(i => i.id === state.selectedDatabase.id), - ...state.appInstances.filter(i => i.id !== state.selectedDatabase.id), - ] - : state.appInstances - - for (let instance of instances_currentFirst) { - await api.post( - `/_builder/instance/${state.appname}/${instance.id}/api/upgradeData`, - { newHierarchy: state.hierarchy, accessLevels: state.accessLevels } - ) - } } -export const newModel = (store, useRoot) => () => { - store.update(state => { - state.currentNodeIsNew = true - const shadowHierarchy = createShadowHierarchy(state.hierarchy) - const parent = useRoot - ? shadowHierarchy - : getNode(shadowHierarchy, state.currentNode.nodeId) - state.errors = [] - state.currentNode = templateApi(shadowHierarchy).getNewModelTemplate( - parent, - "", - true - ) - return state - }) -} +// export const newModel = (store, useRoot) => () => { +// store.update(state => { +// state.currentNodeIsNew = true +// const shadowHierarchy = createShadowHierarchy(state.hierarchy) +// const parent = useRoot +// ? shadowHierarchy +// : getNode(shadowHierarchy, state.currentNode.nodeId) +// state.errors = [] +// state.currentNode = templateApi(shadowHierarchy).getNewModelTemplate( +// parent, +// "", +// true +// ) +// return state +// }) +// } export const selectExistingNode = store => nodeId => { store.update(state => { @@ -145,133 +126,133 @@ export const selectExistingNode = store => nodeId => { }) } -export const newIndex = (store, useRoot) => () => { - store.update(state => { - state.shadowHierarchy = createShadowHierarchy(state.hierarchy) - state.currentNodeIsNew = true - state.errors = [] - const parent = useRoot - ? state.shadowHierarchy - : getNode(state.shadowHierarchy, state.currentNode.nodeId) +// export const newIndex = (store, useRoot) => () => { +// store.update(state => { +// state.shadowHierarchy = createShadowHierarchy(state.hierarchy) +// state.currentNodeIsNew = true +// state.errors = [] +// const parent = useRoot +// ? state.shadowHierarchy +// : getNode(state.shadowHierarchy, state.currentNode.nodeId) - state.currentNode = templateApi(state.shadowHierarchy).getNewIndexTemplate( - parent - ) - return state - }) -} +// state.currentNode = templateApi(state.shadowHierarchy).getNewIndexTemplate( +// parent +// ) +// return state +// }) +// } -export const saveCurrentNode = store => () => { - store.update(state => { - const errors = validate.node(state.currentNode) - state.errors = errors - if (errors.length > 0) { - return state - } - const parentNode = getNode( - state.hierarchy, - state.currentNode.parent().nodeId - ) +// export const saveCurrentNode = store => () => { +// store.update(state => { +// const errors = validate.node(state.currentNode) +// state.errors = errors +// if (errors.length > 0) { +// return state +// } +// const parentNode = getNode( +// state.hierarchy, +// state.currentNode.parent().nodeId +// ) - const existingNode = getNode(state.hierarchy, state.currentNode.nodeId) +// const existingNode = getNode(state.hierarchy, state.currentNode.nodeId) - let index = parentNode.children.length - if (existingNode) { - // remove existing - index = existingNode.parent().children.indexOf(existingNode) - if (isIndex(existingNode)) { - parentNode.indexes = parentNode.indexes.filter( - node => node.nodeId !== existingNode.nodeId - ) - } else { - parentNode.children = parentNode.children.filter( - node => node.nodeId !== existingNode.nodeId - ) - } - } +// let index = parentNode.children.length +// if (existingNode) { +// // remove existing +// index = existingNode.parent().children.indexOf(existingNode) +// if (isIndex(existingNode)) { +// parentNode.indexes = parentNode.indexes.filter( +// node => node.nodeId !== existingNode.nodeId +// ) +// } else { +// parentNode.children = parentNode.children.filter( +// node => node.nodeId !== existingNode.nodeId +// ) +// } +// } - // should add node into existing hierarchy - const cloned = cloneDeep(state.currentNode) - templateApi(state.hierarchy).constructNode(parentNode, cloned) +// // should add node into existing hierarchy +// const cloned = cloneDeep(state.currentNode) +// templateApi(state.hierarchy).constructNode(parentNode, cloned) - if (isIndex(existingNode)) { - parentNode.children = sortBy("name", parentNode.children) - } else { - parentNode.indexes = sortBy("name", parentNode.indexes) - } +// if (isIndex(existingNode)) { +// parentNode.children = sortBy("name", parentNode.children) +// } else { +// parentNode.indexes = sortBy("name", parentNode.indexes) +// } - if (!existingNode && state.currentNode.type === "record") { - const defaultIndex = templateApi(state.hierarchy).getNewIndexTemplate( - cloned.parent() - ) - defaultIndex.name = hierarchyFunctions.isTopLevelIndex(cloned) - ? `all_${cloned.name}s` - : `${cloned.parent().name}_${cloned.name}s` +// if (!existingNode && state.currentNode.type === "record") { +// const defaultIndex = templateApi(state.hierarchy).getNewIndexTemplate( +// cloned.parent() +// ) +// defaultIndex.name = hierarchyFunctions.isTopLevelIndex(cloned) +// ? `all_${cloned.name}s` +// : `${cloned.parent().name}_${cloned.name}s` - defaultIndex.allowedModelNodeIds = [cloned.nodeId] - } +// defaultIndex.allowedModelNodeIds = [cloned.nodeId] +// } - state.currentNodeIsNew = false +// state.currentNodeIsNew = false - saveBackend(state) +// saveBackend(state) - return state - }) -} +// return state +// }) +// } -export const deleteCurrentNode = store => () => { - store.update(state => { - const nodeToDelete = getNode(state.hierarchy, state.currentNode.nodeId) - state.currentNode = hierarchyFunctions.isRoot(nodeToDelete.parent()) - ? state.hierarchy.children.find(node => node !== state.currentNode) - : nodeToDelete.parent() +// export const deleteCurrentNode = store => () => { +// store.update(state => { +// const nodeToDelete = getNode(state.hierarchy, state.currentNode.nodeId) +// state.currentNode = hierarchyFunctions.isRoot(nodeToDelete.parent()) +// ? state.hierarchy.children.find(node => node !== state.currentNode) +// : nodeToDelete.parent() - const isModel = hierarchyFunctions.isModel(nodeToDelete) +// const isModel = hierarchyFunctions.isModel(nodeToDelete) - const check = isModel - ? canDeleteModel(nodeToDelete) - : canDeleteIndex(nodeToDelete) +// const check = isModel +// ? canDeleteModel(nodeToDelete) +// : canDeleteIndex(nodeToDelete) - if (!check.canDelete) { - state.errors = check.errors.map(e => ({ error: e })) - return state - } +// if (!check.canDelete) { +// state.errors = check.errors.map(e => ({ error: e })) +// return state +// } - const recordOrIndexKey = isModel ? "children" : "indexes" +// const recordOrIndexKey = isModel ? "children" : "indexes" - // remove the selected record or index - const newCollection = remove( - node => node.nodeId === nodeToDelete.nodeId, - nodeToDelete.parent()[recordOrIndexKey] - ) +// // remove the selected record or index +// const newCollection = remove( +// node => node.nodeId === nodeToDelete.nodeId, +// nodeToDelete.parent()[recordOrIndexKey] +// ) - nodeToDelete.parent()[recordOrIndexKey] = newCollection +// nodeToDelete.parent()[recordOrIndexKey] = newCollection - state.errors = [] - saveBackend(state) - return state - }) -} +// state.errors = [] +// saveBackend(state) +// return state +// }) +// } -export const saveField = store => field => { - store.update(state => { - state.currentNode.fields = state.currentNode.fields.filter( - f => f.id !== field.id - ) +// export const saveField = store => field => { +// store.update(state => { +// state.currentNode.fields = state.currentNode.fields.filter( +// f => f.id !== field.id +// ) - templateApi(state.hierarchy).addField(state.currentNode, field) - return state - }) -} +// templateApi(state.hierarchy).addField(state.currentNode, field) +// return state +// }) +// } -export const deleteField = store => field => { - store.update(state => { - state.currentNode.fields = state.currentNode.fields.filter( - f => f.name !== field.name - ) - return state - }) -} +// export const deleteField = store => field => { +// store.update(state => { +// state.currentNode.fields = state.currentNode.fields.filter( +// f => f.name !== field.name +// ) +// return state +// }) +// } const incrementAccessLevelsVersion = state => { state.accessLevels.version = state.accessLevels.version diff --git a/packages/builder/src/builderStore/store/index.js b/packages/builder/src/builderStore/store/index.js index d5675f953f..aaac7ba6ec 100644 --- a/packages/builder/src/builderStore/store/index.js +++ b/packages/builder/src/builderStore/store/index.js @@ -43,22 +43,14 @@ export const getStore = () => { libraries: null, showSettings: false, useAnalytics: true, - neoAppId: "84a14e3065c5f15ef8410a5e4c000d68" + appId: "", + clientId: "budibase" } const store = writable(initial) store.setPackage = setPackage(store, initial) - store.newChildModel = backendStoreActions.newModel(store, false) - store.newRootModel = backendStoreActions.newModel(store, true) - store.selectExistingNode = backendStoreActions.selectExistingNode(store) - store.newChildIndex = backendStoreActions.newIndex(store, false) - store.newRootIndex = backendStoreActions.newIndex(store, true) - store.saveCurrentNode = backendStoreActions.saveCurrentNode(store) - store.deleteCurrentNode = backendStoreActions.deleteCurrentNode(store) - store.saveField = backendStoreActions.saveField(store) - store.deleteField = backendStoreActions.deleteField(store) store.saveLevel = backendStoreActions.saveLevel(store) store.deleteLevel = backendStoreActions.deleteLevel(store) store.createDatabaseForApp = backendStoreActions.createDatabaseForApp(store) @@ -102,9 +94,9 @@ export default getStore const setPackage = (store, initial) => async (pkg) => { const [main_screens, unauth_screens] = await Promise.all([ - api.get(`/_builder/api/${pkg.application.name}/pages/main/screens`).then(r => r.json()), + api.get(`/_builder/api/${pkg.application._id}/pages/main/screens`).then(r => r.json()), api - .get(`/_builder/api/${pkg.application.name}/pages/unauthenticated/screens`) + .get(`/_builder/api/${pkg.application._id}/pages/unauthenticated/screens`) .then(r => r.json()), ]) @@ -119,12 +111,13 @@ const setPackage = (store, initial) => async (pkg) => { }, } - initial.libraries = await loadLibs(pkg.application.name, pkg) + initial.libraries = await loadLibs(pkg.application._id, pkg) initial.loadLibraryUrls = pageName => { const libs = libUrlsForPreview(pkg, pageName) return libs } initial.appname = pkg.application.name + initial.appId = pkg.application._id initial.pages = pkg.pages initial.hasAppPackage = true initial.hierarchy = pkg.appDefinition.hierarchy @@ -138,15 +131,7 @@ const setPackage = (store, initial) => async (pkg) => { initial.actions = values(pkg.appDefinition.actions) initial.triggers = pkg.appDefinition.triggers initial.appInstances = pkg.application.instances - initial.appId = pkg.application.id - - if (!!initial.hierarchy && !isEmpty(initial.hierarchy)) { - initial.hierarchy = constructHierarchy(initial.hierarchy) - const shadowHierarchy = createShadowHierarchy(initial.hierarchy) - if (initial.currentNode !== null) { - initial.currentNode = getNode(shadowHierarchy, initial.currentNode.nodeId) - } - } + initial.appId = pkg.application._id store.set(initial) return initial @@ -180,9 +165,6 @@ const importAppDefinition = store => appDefinition => { }) } -const createShadowHierarchy = hierarchy => - constructHierarchy(JSON.parse(JSON.stringify(hierarchy))) - const saveScreen = store => screen => { store.update(s => { return _saveScreen(store, s, screen) @@ -194,7 +176,7 @@ const _saveScreen = async (store, s, screen) => { await api .post( - `/_builder/api/${s.appname}/pages/${s.currentPageName}/screen`, + `/_builder/api/${s.appId}/pages/${s.currentPageName}/screen`, screen ) .then(() => { @@ -227,7 +209,7 @@ const _saveScreen = async (store, s, screen) => { const _saveScreenApi = (screen, s) => api .post( - `/_builder/api/${s.appname}/pages/${s.currentPageName}/screen`, + `/_builder/api/${s.appId}/pages/${s.currentPageName}/screen`, screen ) .then(() => _savePage(s)) @@ -277,7 +259,7 @@ const createGeneratedComponents = store => components => { const doCreate = async () => { for (let c of components) { - await api.post(`/_builder/api/${s.appname}/screen`, c) + await api.post(`/_builder/api/${s.appId}/screen`, c) } await _savePage(s) @@ -302,7 +284,7 @@ const deleteScreen = store => name => { s.currentFrontEndType = "" } - api.delete(`/_builder/api/${s.appname}/screen/${name}`) + api.delete(`/_builder/api/${s.appId}/screen/${name}`) return s }) @@ -330,12 +312,12 @@ const renameScreen = store => (oldname, newname) => { const saveAllChanged = async () => { for (let screenName of changedScreens) { const changedScreen = getExactComponent(screens, screenName) - await api.post(`/_builder/api/${s.appname}/screen`, changedScreen) + await api.post(`/_builder/api/${s.appId}/screen`, changedScreen) } } api - .patch(`/_builder/api/${s.appname}/screen`, { + .patch(`/_builder/api/${s.appId}/screen`, { oldname, newname, }) @@ -362,7 +344,7 @@ const savePage = store => async page => { const addComponentLibrary = store => async lib => { const response = await api.get( - `/_builder/api/${s.appname}/componentlibrary?lib=${encodeURI(lib)}`, + `/_builder/api/${s.appId}/componentlibrary?lib=${encodeURI(lib)}`, undefined, false ) @@ -419,7 +401,7 @@ const removeStylesheet = store => stylesheet => { const _savePage = async s => { const page = s.pages[s.currentPageName] - await api.post(`/_builder/api/${s.appname}/pages/${s.currentPageName}`, { + await api.post(`/_builder/api/${s.appId}/pages/${s.currentPageName}`, { page: { componentLibraries: s.pages.componentLibraries, ...page }, uiFunctions: s.currentPageFunctions, screens: page._screens, diff --git a/packages/builder/src/components/database/ModelDataTable/api.js b/packages/builder/src/components/database/ModelDataTable/api.js index 596b3f695e..a0f3105397 100644 --- a/packages/builder/src/components/database/ModelDataTable/api.js +++ b/packages/builder/src/components/database/ModelDataTable/api.js @@ -1,16 +1,17 @@ import api from "builderStore/api" -import { getNewRecord, getNewInstance } from "components/common/core" -export async function createUser(password, user, { appname, instanceId }) { - const CREATE_USER_URL = `/_builder/instance/${appname}/${instanceId}/api/createUser` - const response = await api.post(CREATE_USER_URL, { user, password }) - return await response.json() +export async function createUser(user, instanceId) { + const CREATE_USER_URL = `/api/${instanceId}/users` + const response = await api.post(CREATE_USER_URL, user) + const json = await response.json() + return json.user; } -export async function createDatabase(appname, instanceName) { - const CREATE_DATABASE_URL = `/_builder/instance/_master/0/api/record/` - const database = getNewInstance(appname, instanceName) - const response = await api.post(CREATE_DATABASE_URL, database) +export async function createDatabase(clientId, appname, instanceName) { + const CREATE_DATABASE_URL = `/api/${clientId}/${appname}/instances` + const response = await api.post(CREATE_DATABASE_URL, { + name: instanceName + }) return await response.json() } diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateDatabase.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateDatabase.svelte index b9208b15a3..b8fc8d9d63 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateDatabase.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateDatabase.svelte @@ -9,8 +9,8 @@ let databaseName async function createDatabase() { - const response = await api.createDatabase($store.appId, databaseName) - store.createDatabaseForApp(response) + const response = await api.createDatabase($store.clientId, $store.appId, databaseName) + store.createDatabaseForApp(response.instance) onClosed() } diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateUser.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateUser.svelte index aeb1ea563d..28e396d5c3 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateUser.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateUser.svelte @@ -7,23 +7,15 @@ let username let password - let accessLevels = [] - $: valid = username && password && accessLevels.length - $: currentAppInfo = { - appname: $store.appname, - instanceId: $backendUiStore.selectedDatabase.id, - } + $: valid = username && password + $: instanceId = $backendUiStore.selectedDatabase.id async function createUser() { - const user = { - name: username, - accessLevels, - enabled: true, - temporaryAccessId: "", - } - const response = await api.createUser(password, user, currentAppInfo) - backendUiStore.actions.users.save(user) + const user = { name: username, username, password } + const response = await api.createUser(user, instanceId); + console.log(response); + backendUiStore.actions.users.create(response) onClosed() } @@ -35,11 +27,6 @@ -