From 7cb3a910a7c48505725427df692855709cfc7981 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 17 Jun 2021 13:57:27 +0100 Subject: [PATCH 1/2] table, view, datasource selection logic --- .../src/components/backend/DataTable/DataTable.svelte | 4 +++- .../DatasourceNavigator/DatasourceNavigator.svelte | 3 --- packages/builder/src/stores/backend/datasources.js | 9 +++++++-- packages/builder/src/stores/backend/queries.js | 8 -------- packages/builder/src/stores/backend/tables.js | 11 +++++++++-- packages/builder/src/stores/backend/views.js | 11 ++++++++++- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index 1fab8bcd32..025a6fc684 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -53,7 +53,9 @@ bind:hideAutocolumns {loading} > - + {#if isInternal} + + {/if} {#if schema && Object.keys(schema).length > 0} {#if !isUsersTable} { update(state => ({ ...state, selected: datasourceId })) - queries.update(state => ({ ...state, selected: null })) + queries.unselect() + tables.unselect() + views.unselect() + }, + unselect: () => { + update(state => ({ ...state, selected: null })) }, updateSchema: async datasource => { let url = `/api/datasources/${datasource._id}/schema` diff --git a/packages/builder/src/stores/backend/queries.js b/packages/builder/src/stores/backend/queries.js index e0a5c9d9fc..2eeae29b9d 100644 --- a/packages/builder/src/stores/backend/queries.js +++ b/packages/builder/src/stores/backend/queries.js @@ -55,10 +55,6 @@ export function createQueriesStore() { }, select: query => { update(state => ({ ...state, selected: query._id })) - datasources.update(state => ({ - ...state, - selected: query.datasourceId, - })) tables.update(state => ({ ...state, selected: null, @@ -66,10 +62,6 @@ export function createQueriesStore() { }, unselect: () => { update(state => ({ ...state, selected: null })) - datasources.update(state => ({ - ...state, - selected: null, - })) }, delete: async query => { const response = await api.delete( diff --git a/packages/builder/src/stores/backend/tables.js b/packages/builder/src/stores/backend/tables.js index 18c748631a..e0b614a63e 100644 --- a/packages/builder/src/stores/backend/tables.js +++ b/packages/builder/src/stores/backend/tables.js @@ -1,5 +1,5 @@ import { writable, get } from "svelte/store" -import { views, queries } from "./" +import { views, queries, datasources } from "./" import { cloneDeep } from "lodash/fp" import api from "builderStore/api" @@ -25,8 +25,9 @@ export function createTablesStore() { selected: table, draft: cloneDeep(table), })) - views.select({ name: table._id }) + views.unselect() queries.unselect() + datasources.unselect() } } @@ -70,6 +71,12 @@ export function createTablesStore() { update, fetch, select, + unselect: () => { + update(state => ({ + ...state, + selected: null, + })) + }, save, init: async () => { const response = await api.get("/api/tables") diff --git a/packages/builder/src/stores/backend/views.js b/packages/builder/src/stores/backend/views.js index d6497bf871..0b15d18fa5 100644 --- a/packages/builder/src/stores/backend/views.js +++ b/packages/builder/src/stores/backend/views.js @@ -1,5 +1,5 @@ import { writable, get } from "svelte/store" -import { tables } from "./" +import { tables, datasources, queries } from "./" import api from "builderStore/api" export function createViewsStore() { @@ -10,11 +10,20 @@ export function createViewsStore() { return { subscribe, + update, select: async view => { update(state => ({ ...state, selected: view, })) + queries.unselect() + datasources.unselect() + }, + unselect: () => { + update(state => ({ + ...state, + selected: null, + })) }, delete: async view => { await api.delete(`/api/views/${view}`) From 90bd99039b6873a83b04e8a63e81e3c8740c1d7c Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 17 Jun 2021 14:06:31 +0100 Subject: [PATCH 2/2] lint --- packages/builder/src/builderStore/api.js | 30 +++--- .../builderStore/store/automation/index.js | 7 +- .../components/backend/DataTable/Table.svelte | 6 +- .../src/components/common/HelpIcon.svelte | 4 +- .../common/bindings/BindingPanel.svelte | 8 +- .../common/bindings/ServerBindingPanel.svelte | 4 +- .../PropertyControls/DataSourceSelect.svelte | 5 +- .../EventsEditor/actions/ExecuteQuery.svelte | 5 +- .../[selectedDatasource]/index.svelte | 16 ++-- .../data/datasource/bb_internal/index.svelte | 19 ++-- packages/builder/src/stores/backend/index.js | 2 +- .../stores/backend/tests/fixtures/queries.js | 6 +- .../server/src/integrations/elasticsearch.js | 3 +- packages/server/src/middleware/authorized.js | 92 +++++++++---------- packages/server/src/middleware/currentapp.js | 8 +- .../src/forms/validation.js | 16 ++-- .../worker/src/api/controllers/admin/email.js | 11 ++- .../src/api/controllers/admin/groups.js | 7 +- .../worker/src/api/controllers/admin/users.js | 7 +- 19 files changed, 137 insertions(+), 119 deletions(-) diff --git a/packages/builder/src/builderStore/api.js b/packages/builder/src/builderStore/api.js index ae81df10f6..2e683238bc 100644 --- a/packages/builder/src/builderStore/api.js +++ b/packages/builder/src/builderStore/api.js @@ -2,21 +2,23 @@ import { store } from "./index" import { get as svelteGet } from "svelte/store" import { removeCookie, Cookies } from "./cookies" -const apiCall = - method => - async (url, body, headers = { "Content-Type": "application/json" }) => { - headers["x-budibase-app-id"] = svelteGet(store).appId - const json = headers["Content-Type"] === "application/json" - const resp = await fetch(url, { - method: method, - body: json ? JSON.stringify(body) : body, - headers, - }) - if (resp.status === 403) { - removeCookie(Cookies.Auth) - } - return resp +const apiCall = method => async ( + url, + body, + headers = { "Content-Type": "application/json" } +) => { + headers["x-budibase-app-id"] = svelteGet(store).appId + const json = headers["Content-Type"] === "application/json" + const resp = await fetch(url, { + method: method, + body: json ? JSON.stringify(body) : body, + headers, + }) + if (resp.status === 403) { + removeCookie(Cookies.Auth) } + return resp +} export const post = apiCall("POST") export const get = apiCall("GET") diff --git a/packages/builder/src/builderStore/store/automation/index.js b/packages/builder/src/builderStore/store/automation/index.js index c372f27bb7..7a01bccfab 100644 --- a/packages/builder/src/builderStore/store/automation/index.js +++ b/packages/builder/src/builderStore/store/automation/index.js @@ -100,10 +100,9 @@ const automationActions = store => ({ }, deleteAutomationBlock: block => { store.update(state => { - const idx = - state.selectedAutomation.automation.definition.steps.findIndex( - x => x.id === block.id - ) + const idx = state.selectedAutomation.automation.definition.steps.findIndex( + x => x.id === block.id + ) state.selectedAutomation.deleteBlock(block.id) // Select next closest step diff --git a/packages/builder/src/components/backend/DataTable/Table.svelte b/packages/builder/src/components/backend/DataTable/Table.svelte index f40462a8a8..a8e237d4fd 100644 --- a/packages/builder/src/components/backend/DataTable/Table.svelte +++ b/packages/builder/src/components/backend/DataTable/Table.svelte @@ -9,7 +9,11 @@ import CreateEditRow from "./modals/CreateEditRow.svelte" import CreateEditUser from "./modals/CreateEditUser.svelte" import CreateEditColumn from "./modals/CreateEditColumn.svelte" - import { TableNames, UNEDITABLE_USER_FIELDS, BUDIBASE_INTERNAL_DB } from "constants" + import { + TableNames, + UNEDITABLE_USER_FIELDS, + BUDIBASE_INTERNAL_DB, + } from "constants" import RoleCell from "./cells/RoleCell.svelte" export let schema = {} diff --git a/packages/builder/src/components/common/HelpIcon.svelte b/packages/builder/src/components/common/HelpIcon.svelte index 3941dabf24..bebc67e5f2 100644 --- a/packages/builder/src/components/common/HelpIcon.svelte +++ b/packages/builder/src/components/common/HelpIcon.svelte @@ -2,7 +2,7 @@ import { Icon } from "@budibase/bbui" - + @@ -14,4 +14,4 @@ right: var(--spacing-m); border-radius: 55%; } - \ No newline at end of file + diff --git a/packages/builder/src/components/common/bindings/BindingPanel.svelte b/packages/builder/src/components/common/bindings/BindingPanel.svelte index 01e0c5918b..37e7f520f3 100644 --- a/packages/builder/src/components/common/bindings/BindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/BindingPanel.svelte @@ -59,7 +59,9 @@
Columns
    - {#each context.filter( context => context.readableBinding.match(searchRgx) ) as { readableBinding }} + {#each context.filter(context => + context.readableBinding.match(searchRgx) + ) as { readableBinding }}
  • { value = addToText(value, getCaretPosition(), readableBinding) @@ -75,7 +77,9 @@
    Components
      - {#each instance.filter( instance => instance.readableBinding.match(searchRgx) ) as { readableBinding }} + {#each instance.filter(instance => + instance.readableBinding.match(searchRgx) + ) as { readableBinding }}
    • addToText(readableBinding)}> {readableBinding}
    • diff --git a/packages/builder/src/components/common/bindings/ServerBindingPanel.svelte b/packages/builder/src/components/common/bindings/ServerBindingPanel.svelte index 2c0e33227b..dc921dfb27 100644 --- a/packages/builder/src/components/common/bindings/ServerBindingPanel.svelte +++ b/packages/builder/src/components/common/bindings/ServerBindingPanel.svelte @@ -49,7 +49,9 @@
      {#each categories as [categoryName, bindings]} {categoryName} - {#each bindings.filter( binding => binding.label.match(searchRgx) ) as binding} + {#each bindings.filter(binding => + binding.label.match(searchRgx) + ) as binding}
      { diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataSourceSelect.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataSourceSelect.svelte index 43f9837232..57c64ca0ed 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataSourceSelect.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/DataSourceSelect.svelte @@ -103,9 +103,8 @@ } function fetchQueryDefinition(query) { - const source = $datasources.list.find( - ds => ds._id === query.datasourceId - ).source + const source = $datasources.list.find(ds => ds._id === query.datasourceId) + .source return $integrations[source].query[query.queryVerb] } diff --git a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/ExecuteQuery.svelte b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/ExecuteQuery.svelte index 44f349a324..8c10b47a4d 100644 --- a/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/ExecuteQuery.svelte +++ b/packages/builder/src/components/design/PropertiesPanel/PropertyControls/EventsEditor/actions/ExecuteQuery.svelte @@ -18,9 +18,8 @@ ) function fetchQueryDefinition(query) { - const source = $datasources.list.find( - ds => ds._id === query.datasourceId - ).source + const source = $datasources.list.find(ds => ds._id === query.datasourceId) + .source return $integrations[source].query[query.queryVerb] } diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/index.svelte index cd3ef1f5c5..8084e2ee63 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/index.svelte @@ -1,12 +1,7 @@ @@ -12,14 +10,9 @@ - - Budibase Internal DB - + Budibase Internal DB - - Stuff about the internal table - - - - - \ No newline at end of file +
      + +
      + diff --git a/packages/builder/src/stores/backend/index.js b/packages/builder/src/stores/backend/index.js index 9820f55c94..e020baaf4b 100644 --- a/packages/builder/src/stores/backend/index.js +++ b/packages/builder/src/stores/backend/index.js @@ -6,4 +6,4 @@ export { permissions } from "./permissions" export { roles } from "./roles" export { datasources } from "./datasources" export { integrations } from "./integrations" -export { queries } from "./queries" \ No newline at end of file +export { queries } from "./queries" diff --git a/packages/builder/src/stores/backend/tests/fixtures/queries.js b/packages/builder/src/stores/backend/tests/fixtures/queries.js index f5e595249a..7815d61ea5 100644 --- a/packages/builder/src/stores/backend/tests/fixtures/queries.js +++ b/packages/builder/src/stores/backend/tests/fixtures/queries.js @@ -9,7 +9,8 @@ export const SOME_QUERY = { queryVerb: "read", schema: {}, name: "Speakers", - _id: "query_datasource_04b003a7b4a8428eadd3bb2f7eae0255_bcb8ffc6fcbc484e8d63121fc0bf986f", + _id: + "query_datasource_04b003a7b4a8428eadd3bb2f7eae0255_bcb8ffc6fcbc484e8d63121fc0bf986f", _rev: "2-941f8699eb0adf995f8bd59c99203b26", readable: true, } @@ -74,7 +75,8 @@ export const SAVE_QUERY_RESPONSE = { }, }, name: "Speakers", - _id: "query_datasource_04b003a7b4a8428eadd3bb2f7eae0255_bcb8ffc6fcbc484e8d63121fc0bf986f", + _id: + "query_datasource_04b003a7b4a8428eadd3bb2f7eae0255_bcb8ffc6fcbc484e8d63121fc0bf986f", _rev: "3-5a64adef494b1e9c793dc91b51ce73c6", readable: true, } diff --git a/packages/server/src/integrations/elasticsearch.js b/packages/server/src/integrations/elasticsearch.js index 3a52a0278b..be1b945893 100644 --- a/packages/server/src/integrations/elasticsearch.js +++ b/packages/server/src/integrations/elasticsearch.js @@ -2,7 +2,8 @@ const { Client } = require("@elastic/elasticsearch") const { QUERY_TYPES, FIELD_TYPES } = require("./Integration") const SCHEMA = { - docs: "https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html", + docs: + "https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html", description: "Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents.", friendlyName: "ElasticSearch", diff --git a/packages/server/src/middleware/authorized.js b/packages/server/src/middleware/authorized.js index bd064f7e66..8ed4c41db7 100644 --- a/packages/server/src/middleware/authorized.js +++ b/packages/server/src/middleware/authorized.js @@ -14,52 +14,50 @@ const WEBHOOK_ENDPOINTS = new RegExp( ["webhooks/trigger", "webhooks/schema"].join("|") ) -module.exports = - (permType, permLevel = null) => - async (ctx, next) => { - // webhooks don't need authentication, each webhook unique - if (WEBHOOK_ENDPOINTS.test(ctx.request.url)) { - return next() - } - - if (!ctx.user) { - return ctx.throw(403, "No user info found") - } - - // check general builder stuff, this middleware is a good way - // to find API endpoints which are builder focused - await builderMiddleware(ctx, permType) - - const isAuthed = ctx.isAuthenticated - const { basePermissions, permissions } = await getUserPermissions( - ctx.appId, - ctx.roleId - ) - - // builders for now have permission to do anything - // TODO: in future should consider separating permissions with an require("@budibase/auth").isClient check - let isBuilder = ctx.user && ctx.user.builder && ctx.user.builder.global - const isBuilderApi = permType === PermissionTypes.BUILDER - if (isBuilder) { - return next() - } else if (isBuilderApi && !isBuilder) { - return ctx.throw(403, "Not Authorized") - } - - if ( - hasResource(ctx) && - doesHaveResourcePermission(permissions, permLevel, ctx) - ) { - return next() - } - - if (!isAuthed) { - ctx.throw(403, "Session not authenticated") - } - - if (!doesHaveBasePermission(permType, permLevel, basePermissions)) { - ctx.throw(403, "User does not have permission") - } - +module.exports = (permType, permLevel = null) => async (ctx, next) => { + // webhooks don't need authentication, each webhook unique + if (WEBHOOK_ENDPOINTS.test(ctx.request.url)) { return next() } + + if (!ctx.user) { + return ctx.throw(403, "No user info found") + } + + // check general builder stuff, this middleware is a good way + // to find API endpoints which are builder focused + await builderMiddleware(ctx, permType) + + const isAuthed = ctx.isAuthenticated + const { basePermissions, permissions } = await getUserPermissions( + ctx.appId, + ctx.roleId + ) + + // builders for now have permission to do anything + // TODO: in future should consider separating permissions with an require("@budibase/auth").isClient check + let isBuilder = ctx.user && ctx.user.builder && ctx.user.builder.global + const isBuilderApi = permType === PermissionTypes.BUILDER + if (isBuilder) { + return next() + } else if (isBuilderApi && !isBuilder) { + return ctx.throw(403, "Not Authorized") + } + + if ( + hasResource(ctx) && + doesHaveResourcePermission(permissions, permLevel, ctx) + ) { + return next() + } + + if (!isAuthed) { + ctx.throw(403, "Session not authenticated") + } + + if (!doesHaveBasePermission(permType, permLevel, basePermissions)) { + ctx.throw(403, "User does not have permission") + } + + return next() +} diff --git a/packages/server/src/middleware/currentapp.js b/packages/server/src/middleware/currentapp.js index 683b7f8ef3..19d0afd560 100644 --- a/packages/server/src/middleware/currentapp.js +++ b/packages/server/src/middleware/currentapp.js @@ -1,5 +1,9 @@ -const { getAppId, setCookie, getCookie, clearCookie } = - require("@budibase/auth").utils +const { + getAppId, + setCookie, + getCookie, + clearCookie, +} = require("@budibase/auth").utils const { Cookies } = require("@budibase/auth").constants const { getRole } = require("@budibase/auth/roles") const { getGlobalSelf } = require("../utilities/workerRequests") diff --git a/packages/standard-components/src/forms/validation.js b/packages/standard-components/src/forms/validation.js index b1df80509f..ebdb3b3dab 100644 --- a/packages/standard-components/src/forms/validation.js +++ b/packages/standard-components/src/forms/validation.js @@ -90,17 +90,15 @@ const numericalConstraint = (constraint, error) => value => { return null } -const inclusionConstraint = - (options = []) => - value => { - if (value == null || value === "") { - return null - } - if (!options.includes(value)) { - return "Invalid value" - } +const inclusionConstraint = (options = []) => value => { + if (value == null || value === "") { return null } + if (!options.includes(value)) { + return "Invalid value" + } + return null +} const dateConstraint = (dateString, isEarliest) => { const dateLimit = Date.parse(dateString) diff --git a/packages/worker/src/api/controllers/admin/email.js b/packages/worker/src/api/controllers/admin/email.js index 6e16fd060c..c4b17ee980 100644 --- a/packages/worker/src/api/controllers/admin/email.js +++ b/packages/worker/src/api/controllers/admin/email.js @@ -5,8 +5,15 @@ const authPkg = require("@budibase/auth") const GLOBAL_DB = authPkg.StaticDatabases.GLOBAL.name exports.sendEmail = async ctx => { - const { groupId, email, userId, purpose, contents, from, subject } = - ctx.request.body + const { + groupId, + email, + userId, + purpose, + contents, + from, + subject, + } = ctx.request.body let user if (userId) { const db = new CouchDB(GLOBAL_DB) diff --git a/packages/worker/src/api/controllers/admin/groups.js b/packages/worker/src/api/controllers/admin/groups.js index 330fb38282..8a70721431 100644 --- a/packages/worker/src/api/controllers/admin/groups.js +++ b/packages/worker/src/api/controllers/admin/groups.js @@ -1,6 +1,9 @@ const CouchDB = require("../../../db") -const { getGroupParams, generateGroupID, StaticDatabases } = - require("@budibase/auth").db +const { + getGroupParams, + generateGroupID, + StaticDatabases, +} = require("@budibase/auth").db const GLOBAL_DB = StaticDatabases.GLOBAL.name diff --git a/packages/worker/src/api/controllers/admin/users.js b/packages/worker/src/api/controllers/admin/users.js index 5b95b2808f..6afd4ecbfd 100644 --- a/packages/worker/src/api/controllers/admin/users.js +++ b/packages/worker/src/api/controllers/admin/users.js @@ -1,6 +1,9 @@ const CouchDB = require("../../../db") -const { generateGlobalUserID, getGlobalUserParams, StaticDatabases } = - require("@budibase/auth").db +const { + generateGlobalUserID, + getGlobalUserParams, + StaticDatabases, +} = require("@budibase/auth").db const { hash, getGlobalUserByEmail } = require("@budibase/auth").utils const { UserStatus, EmailTemplatePurpose } = require("../../../constants") const { checkInviteCode } = require("../../../utilities/redis")