diff --git a/.gitignore b/.gitignore index 3a5fc5dc7b..086813c97e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ builder/* .temp/ packages/server/runtime_apps/ .idea/ +bb-airgapped.tar.gz # Logs logs diff --git a/hosting/scripts/airgapped/airgappedDockerBuild.js b/hosting/scripts/airgapped/airgappedDockerBuild.js new file mode 100755 index 0000000000..5be19fdeb8 --- /dev/null +++ b/hosting/scripts/airgapped/airgappedDockerBuild.js @@ -0,0 +1,51 @@ +const fs = require("fs") +const { execSync } = require("child_process") +const path = require("path") + +const IMAGES = { + worker: "budibase/worker", + apps: "budibase/apps", + proxy: "envoyproxy/envoy:v1.16-latest", + minio: "minio/minio", + couch: "ibmcom/couchdb3", + curl: "curlimages/curl", + redis: "redis", + watchtower: "containrrr/watchtower" +} + +const FILES = { + COMPOSE: "docker-compose.yaml", + ENVOY: "envoy.yaml", + PROPERTIES: "hosting.properties" +} + +const OUTPUT_DIR = path.join(__dirname, "../", "bb-airgapped") + +function copyFile(file) { + fs.copyFileSync( + path.join(__dirname, "../", "../", file), + path.join(OUTPUT_DIR, file) + ) +} + +// create output dir +console.log(`Creating ${OUTPUT_DIR} for build..`) +fs.rmdirSync(OUTPUT_DIR, { recursive: true }) +fs.mkdirSync(OUTPUT_DIR) + +// package images into tar files +for (let image in IMAGES) { + console.log(`Creating tar for ${image}..`) + execSync(`docker save ${IMAGES[image]} -o ${OUTPUT_DIR}/${image}.tar`) +} + +// copy config files +copyFile(FILES.COMPOSE) +copyFile(FILES.ENVOY) +copyFile(FILES.PROPERTIES) + +// compress +execSync(`tar -czf bb-airgapped.tar.gz hosting/scripts/bb-airgapped`) + +// clean up +fs.rmdirSync(OUTPUT_DIR, { recursive: true }) \ No newline at end of file diff --git a/lerna.json b/lerna.json index aebd39acab..18f9328afd 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "0.9.173-alpha.3", + "version": "0.9.176-alpha.3", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index eb7b7167f1..f0326782d1 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "build:docker": "lerna run build:docker && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -", "build:docker:production": "lerna run build:docker && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION release && cd -", "build:docker:develop": "node scripts/pinVersions && lerna run build:docker && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh develop && cd -", + "build:docker:airgap": "node hosting/scripts/airgapped/airgappedDockerBuild", "release:helm": "./scripts/release_helm_chart.sh", "env:multi:enable": "lerna run env:multi:enable", "env:multi:disable": "lerna run env:multi:disable", diff --git a/packages/auth/package.json b/packages/auth/package.json index 5f6866e9ed..b5f27ca059 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/auth", - "version": "0.9.173-alpha.3", + "version": "0.9.176-alpha.3", "description": "Authentication middlewares for budibase builder and apps", "main": "src/index.js", "author": "Budibase", diff --git a/packages/auth/src/middleware/passport/local.js b/packages/auth/src/middleware/passport/local.js index 0db40d64eb..f95c3a173e 100644 --- a/packages/auth/src/middleware/passport/local.js +++ b/packages/auth/src/middleware/passport/local.js @@ -9,6 +9,8 @@ const { createASession } = require("../../security/sessions") const { getTenantId } = require("../../tenancy") const INVALID_ERR = "Invalid Credentials" +const SSO_NO_PASSWORD = "SSO user does not have a password set" +const EXPIRED = "This account has expired. Please reset your password" exports.options = { passReqToCallback: true, @@ -36,6 +38,19 @@ exports.authenticate = async function (ctx, email, password, done) { return authError(done, INVALID_ERR) } + // check that the user has a stored password before proceeding + if (!dbUser.password) { + if ( + (dbUser.account && dbUser.account.authType === "sso") || // root account sso + dbUser.thirdPartyProfile // internal sso + ) { + return authError(done, SSO_NO_PASSWORD) + } + + console.error("Non SSO usser has no password set", dbUser) + return authError(done, EXPIRED) + } + // authenticate if (await compare(password, dbUser.password)) { const sessionId = newid() diff --git a/packages/auth/src/utils.js b/packages/auth/src/utils.js index e1df289d6e..f7ab5d6990 100644 --- a/packages/auth/src/utils.js +++ b/packages/auth/src/utils.js @@ -181,8 +181,8 @@ exports.saveUser = async ( // check budibase users in other tenants if (env.MULTI_TENANCY) { - dbUser = await getTenantUser(email) - if (dbUser != null && dbUser.tenantId !== tenantId) { + const tenantUser = await getTenantUser(email) + if (tenantUser != null && tenantUser.tenantId !== tenantId) { throw `Email address ${email} already in use.` } } diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 80bacada00..0d1c5c15bc 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "0.9.173-alpha.3", + "version": "0.9.176-alpha.3", "license": "AGPL-3.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -51,6 +51,7 @@ "@spectrum-css/fieldlabel": "^3.0.1", "@spectrum-css/icon": "^3.0.1", "@spectrum-css/illustratedmessage": "^3.0.2", + "@spectrum-css/inlinealert": "^2.0.1", "@spectrum-css/inputgroup": "^3.0.2", "@spectrum-css/label": "^2.0.10", "@spectrum-css/link": "^3.1.1", diff --git a/packages/bbui/src/InlineAlert/InlineAlert.svelte b/packages/bbui/src/InlineAlert/InlineAlert.svelte new file mode 100644 index 0000000000..a7740a68a7 --- /dev/null +++ b/packages/bbui/src/InlineAlert/InlineAlert.svelte @@ -0,0 +1,51 @@ + + +
+ +
{header}
+
{message}
+ {#if onConfirm} + + {/if} +
+ + diff --git a/packages/bbui/src/index.js b/packages/bbui/src/index.js index 08ece6b93c..377d451604 100644 --- a/packages/bbui/src/index.js +++ b/packages/bbui/src/index.js @@ -58,6 +58,7 @@ export { default as Pagination } from "./Pagination/Pagination.svelte" export { default as Badge } from "./Badge/Badge.svelte" export { default as StatusLight } from "./StatusLight/StatusLight.svelte" export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte" +export { default as InlineAlert } from "./InlineAlert/InlineAlert.svelte" // Typography export { default as Body } from "./Typography/Body.svelte" diff --git a/packages/bbui/yarn.lock b/packages/bbui/yarn.lock index a492c83266..a102e6c148 100644 --- a/packages/bbui/yarn.lock +++ b/packages/bbui/yarn.lock @@ -136,6 +136,11 @@ resolved "https://registry.yarnpkg.com/@spectrum-css/illustratedmessage/-/illustratedmessage-3.0.2.tgz#6a480be98b027e050b086e7899e40d87adb0a8c0" integrity sha512-dqnE8X27bGcO0HN8+dYx8O4o0dNNIAqeivOzDHhe2El+V4dTzMrNIerF6G0NLm3GjVf6XliwmitsZK+K6FmbtA== +"@spectrum-css/inlinealert@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@spectrum-css/inlinealert/-/inlinealert-2.0.1.tgz#7521f88f6c845806403cc7d925773c7414e204a2" + integrity sha512-Xy5RCOwgurqUXuGQCsEDUduDd5408bmEpmFg+feynG7VFUgLFZWBeylSENB/OqjlFtO76PHXNVdHkhDscPIHTA== + "@spectrum-css/inputgroup@^3.0.2": version "3.0.2" resolved "https://registry.yarnpkg.com/@spectrum-css/inputgroup/-/inputgroup-3.0.2.tgz#f1b13603832cbd22394f3d898af13203961f8691" diff --git a/packages/builder/package.json b/packages/builder/package.json index d262839f12..56811c6d11 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "0.9.173-alpha.3", + "version": "0.9.176-alpha.3", "license": "AGPL-3.0", "private": true, "scripts": { @@ -65,10 +65,10 @@ } }, "dependencies": { - "@budibase/bbui": "^0.9.173-alpha.3", - "@budibase/client": "^0.9.173-alpha.3", + "@budibase/bbui": "^0.9.176-alpha.3", + "@budibase/client": "^0.9.176-alpha.3", "@budibase/colorpicker": "1.1.2", - "@budibase/string-templates": "^0.9.173-alpha.3", + "@budibase/string-templates": "^0.9.176-alpha.3", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/components/backend/DataTable/DataTable.svelte b/packages/builder/src/components/backend/DataTable/DataTable.svelte index 336bb51670..6bebf2ca02 100644 --- a/packages/builder/src/components/backend/DataTable/DataTable.svelte +++ b/packages/builder/src/components/backend/DataTable/DataTable.svelte @@ -4,6 +4,7 @@ import CreateRowButton from "./buttons/CreateRowButton.svelte" import CreateColumnButton from "./buttons/CreateColumnButton.svelte" import CreateViewButton from "./buttons/CreateViewButton.svelte" + import ExistingRelationshipButton from "./buttons/ExistingRelationshipButton.svelte" import ExportButton from "./buttons/ExportButton.svelte" import EditRolesButton from "./buttons/EditRolesButton.svelte" import ManageAccessButton from "./buttons/ManageAccessButton.svelte" @@ -98,9 +99,7 @@ on:updatecolumns={onUpdateColumns} on:updaterows={onUpdateRows} > - {#if isInternal} - - {/if} + {#if schema && Object.keys(schema).length > 0} {#if !isUsersTable} {/if} + {#if !isInternal} + + {/if} diff --git a/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte b/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte index e82c55679a..25ad67b52e 100644 --- a/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte +++ b/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte @@ -16,8 +16,8 @@ export let value = defaultValue || (meta.type === "boolean" ? false : "") export let readonly - $: type = meta.type - $: label = capitalise(meta.name) + $: type = meta?.type + $: label = meta.name ? capitalise(meta.name) : "" {#if type === "options"} diff --git a/packages/builder/src/components/backend/DataTable/Table.svelte b/packages/builder/src/components/backend/DataTable/Table.svelte index 78c3cc37f8..512324254c 100644 --- a/packages/builder/src/components/backend/DataTable/Table.svelte +++ b/packages/builder/src/components/backend/DataTable/Table.svelte @@ -129,7 +129,7 @@ bind:selectedRows allowSelectRows={allowEditing && !isUsersTable} allowEditRows={allowEditing} - allowEditColumns={allowEditing && isInternal} + allowEditColumns={allowEditing} showAutoColumns={!hideAutocolumns} on:editcolumn={e => editColumn(e.detail)} on:editrow={e => editRow(e.detail)} diff --git a/packages/builder/src/components/backend/DataTable/buttons/ExistingRelationshipButton.svelte b/packages/builder/src/components/backend/DataTable/buttons/ExistingRelationshipButton.svelte new file mode 100644 index 0000000000..4a7abf487f --- /dev/null +++ b/packages/builder/src/components/backend/DataTable/buttons/ExistingRelationshipButton.svelte @@ -0,0 +1,54 @@ + + +{#if table.sourceId} +
+ + Define existing relationship + +
+ + + +{/if} diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte index cd437bcad2..ebfea9cee6 100644 --- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte @@ -31,6 +31,9 @@ const AUTO_TYPE = "auto" const FORMULA_TYPE = FIELDS.FORMULA.type const LINK_TYPE = FIELDS.LINK.type + const STRING_TYPE = FIELDS.STRING.type + const NUMBER_TYPE = FIELDS.NUMBER.type + const dispatch = createEventDispatcher() const PROHIBITED_COLUMN_NAMES = ["type", "_id", "_rev", "tableId"] const { hide } = getContext(Context.Modal) @@ -55,8 +58,9 @@ let confirmDeleteDialog let deletion + $: checkConstraints(field) $: tableOptions = $tables.list.filter( - table => table._id !== $tables.draft._id && table.type !== "external" + opt => opt._id !== $tables.draft._id && opt.type === table.type ) $: required = !!field?.constraints?.presence || primaryDisplay $: uneditable = @@ -83,6 +87,7 @@ $: canBeRequired = field.type !== LINK_TYPE && !uneditable && field.type !== AUTO_TYPE $: relationshipOptions = getRelationshipOptions(field) + $: external = table.type === "external" async function saveColumn() { if (field.type === AUTO_TYPE) { @@ -193,6 +198,45 @@ }, ] } + + function getAllowedTypes() { + if (!external) { + return [ + ...Object.values(fieldDefinitions), + { name: "Auto Column", type: AUTO_TYPE }, + ] + } else { + return [ + FIELDS.STRING, + FIELDS.LONGFORM, + FIELDS.OPTIONS, + FIELDS.DATETIME, + FIELDS.NUMBER, + FIELDS.BOOLEAN, + FIELDS.ARRAY, + FIELDS.FORMULA, + FIELDS.LINK, + ] + } + } + + function checkConstraints(fieldToCheck) { + // most types need this, just make sure its always present + if (fieldToCheck && !fieldToCheck.constraints) { + fieldToCheck.constraints = {} + } + // some string types may have been built by server, may not always have constraints + if (fieldToCheck.type === STRING_TYPE && !fieldToCheck.constraints.length) { + fieldToCheck.constraints.length = {} + } + // some number types made server-side will be missing constraints + if ( + fieldToCheck.type === NUMBER_TYPE && + !fieldToCheck.constraints.numericality + ) { + fieldToCheck.constraints.numericality = {} + } + } field.name} getOptionValue={field => field.type} /> @@ -245,7 +286,7 @@ {/if} - {#if canBeSearched} + {#if canBeSearched && !external}
($touched.from = true)} bind:error={errors.from} bind:value={toRelationship.tableId} diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/CreateEditRelationship/TableSelect.svelte b/packages/builder/src/components/backend/Datasources/TableSelect.svelte similarity index 100% rename from packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/CreateEditRelationship/TableSelect.svelte rename to packages/builder/src/components/backend/Datasources/TableSelect.svelte diff --git a/packages/builder/src/components/backend/TableNavigator/popovers/EditTablePopover.svelte b/packages/builder/src/components/backend/TableNavigator/popovers/EditTablePopover.svelte index 2513c6c7e5..04094b881a 100644 --- a/packages/builder/src/components/backend/TableNavigator/popovers/EditTablePopover.svelte +++ b/packages/builder/src/components/backend/TableNavigator/popovers/EditTablePopover.svelte @@ -1,7 +1,7 @@ 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 fc82e3a11c..b1867db248 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,16 +1,25 @@ @@ -117,8 +127,8 @@ /> - - + + {#if datasource && integration} @@ -154,15 +164,15 @@
Tables
- {#if plusTables && plusTables.length !== 0} - - {/if}
- +
@@ -171,6 +181,14 @@ your tables directly from the database and you can use them without having to write any queries at all. + {#if schemaError} + + {/if}
{#each plusTables as table}
onClickTable(table)}> @@ -179,14 +197,23 @@

{/each} +
+ +
{#if plusTables?.length !== 0}
Relationships - + Define existing relationship +
Tell budibase how your tables are related to get even more smart @@ -301,11 +328,14 @@ .table-buttons { display: grid; - grid-gap: var(--spacing-l); grid-template-columns: 1fr 1fr; } .table-buttons div { grid-column-end: -1; } + + .add-table { + margin-top: var(--spacing-m); + } diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/modals/CreateExternalTableModal.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/modals/CreateExternalTableModal.svelte new file mode 100644 index 0000000000..1d9e246d20 --- /dev/null +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/modals/CreateExternalTableModal.svelte @@ -0,0 +1,45 @@ + + + + Provide a name for your new table; you can add columns once it is created. + + diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/modals/EditDisplayColumnsModal.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/modals/EditDisplayColumnsModal.svelte deleted file mode 100644 index ffb6b3c58e..0000000000 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[selectedDatasource]/modals/EditDisplayColumnsModal.svelte +++ /dev/null @@ -1,43 +0,0 @@ - - - - Select the columns that will be shown when displaying relationships. - {#each plusTables as table} -