From 9260935572b87d0b61d4c4d025c695e621b9341e Mon Sep 17 00:00:00 2001 From: Dean Date: Thu, 18 Aug 2022 10:59:40 +0100 Subject: [PATCH 01/17] Added scope customisation to the OIDC SSO configuration. Users can add or remove whichever scopes they like except 'openid'. They can revert to our core default values if they run into any issues --- packages/bbui/src/Tags/Tag.svelte | 3 +- .../builder/portal/manage/auth/index.svelte | 203 +++++++++++++++++- .../worker/src/api/controllers/global/auth.ts | 15 +- .../worker/src/api/routes/global/configs.js | 1 + 4 files changed, 219 insertions(+), 3 deletions(-) diff --git a/packages/bbui/src/Tags/Tag.svelte b/packages/bbui/src/Tags/Tag.svelte index f7089decdb..9c4cb6e583 100644 --- a/packages/bbui/src/Tags/Tag.svelte +++ b/packages/bbui/src/Tags/Tag.svelte @@ -8,6 +8,7 @@ export let invalid = false export let disabled = false export let closable = false + export let onClick
{#if closable} - + {/if}
diff --git a/packages/builder/src/pages/builder/portal/manage/auth/index.svelte b/packages/builder/src/pages/builder/portal/manage/auth/index.svelte index bc77329a32..ffc5bed7ce 100644 --- a/packages/builder/src/pages/builder/portal/manage/auth/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/auth/index.svelte @@ -18,6 +18,8 @@ Body, Select, Toggle, + Tag, + Tags, } from "@budibase/bbui" import { onMount } from "svelte" import { API } from "api" @@ -208,6 +210,7 @@ providers[res.type]._id = res._id }) notifications.success(`Settings saved`) + scopesFields[0].editing = false }) .catch(() => { notifications.error("Failed to update auth settings") @@ -215,6 +218,21 @@ } } + let defaultScopes = ["profile", "email", "offline_access"] + + const refreshScopes = idx => { + providers.oidc.config.configs[idx]["scopes"] = + providers.oidc.config.configs[idx]["scopes"] + } + + let scopesFields = [ + { + editing: false, + inputText: null, + error: null, + }, + ] + onMount(async () => { try { await organisation.init() @@ -276,7 +294,7 @@ if (!oidcDoc?._id) { providers.oidc = { type: ConfigTypes.OIDC, - config: { configs: [{ activated: true }] }, + config: { configs: [{ activated: true, scopes: defaultScopes }] }, } } else { originalOidcDoc = cloneDeep(oidcDoc) @@ -397,10 +415,193 @@ /> + + + +
Advanced
+
+ + Changes to your authentication scopes will only take effect when you + next log in. Please refer to your vendor documentation before + modification. + + +
+ + {#if scopesFields[0].editing} + + { + if (!scopesFields[0].inputText) { + scopesFields[0].error = null + } + if ( + e.key === "Enter" || + e.keyCode === 13 || + e.code == "Space" || + e.keyCode == 32 + ) { + let scopes = providers.oidc.config.configs[0]["scopes"] + ? providers.oidc.config.configs[0]["scopes"] + : [...defaultScopes] + + let update = scopesFields[0].inputText.trim() + + if (/[\\"\s]/.test(update)) { + scopesFields[0].error = + "Auth scopes cannot contain spaces, double quotes or backslashes" + return + } else if (scopes.indexOf(update) > -1) { + scopesFields[0].error = "Auth scope already exists" + return + } else if (!update.length) { + scopesFields[0].inputText = null + scopesFields[0].error = null + return + } else { + scopesFields[0].error = null + } + + if (scopes.indexOf(update) == -1) { + scopes.push(update) + providers.oidc.config.configs[0]["scopes"] = scopes + } + scopesFields[0].inputText = null + } + }} + /> + + {/if} + +
+ + + openid + + {#each providers.oidc.config.configs[0]["scopes"] || [...defaultScopes] as tag, idx} + { + let idxScopes = providers.oidc.config.configs[0]["scopes"] + if (idxScopes.length == 1) { + idxScopes.pop() + } else { + idxScopes.splice(idx, 1) + refreshScopes(0) + } + }} + > + {tag} + + {/each} + + {#if !scopesFields[0].editing} + { + if (!providers.oidc.config.configs[0]) { + providers.oidc.config.configs[0]["scopes"] = [ + ...defaultScopes, + ] + } + scopesFields[0].editing = !scopesFields[0].editing + }} + > + Edit + + {/if} + +
+ + {#if scopesFields[0].editing} +
+ + +
+ {/if} +
+
+
{/if} diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js index 8f0baf08be..1ecd8f474a 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/index.js @@ -15,3 +15,4 @@ export { default as S3Upload } from "./S3Upload.svelte" export { default as ExportData } from "./ExportData.svelte" export { default as ContinueIf } from "./ContinueIf.svelte" export { default as UpdateFieldValue } from "./UpdateFieldValue.svelte" +export { default as ShowNotification } from "./ShowNotification.svelte" diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json index c00b8dddec..5d11a27636 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json @@ -110,6 +110,12 @@ "type": "logic", "component": "ContinueIf", "dependsOnFeature": "continueIfAction" + }, + { + "name": "Show Notification", + "type": "application", + "component": "ShowNotification", + "dependsOnFeature": "showNotificationAction" } ] } \ No newline at end of file diff --git a/packages/client/manifest.json b/packages/client/manifest.json index bbfd613835..87cc8b2567 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -8,7 +8,8 @@ "devicePreview": true, "messagePassing": true, "rowSelection": true, - "continueIfAction": true + "continueIfAction": true, + "showNotificationAction": true }, "layout": { "name": "Layout", diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js index 558cab8f21..7cc0679a2d 100644 --- a/packages/client/src/utils/buttonActions.js +++ b/packages/client/src/utils/buttonActions.js @@ -300,6 +300,14 @@ const continueIfHandler = action => { } } +const showNotificationHandler = action => { + const { message, type } = action.parameters + if (!message || !type) { + return + } + notificationStore.actions[type]?.(message) +} + const handlerMap = { ["Save Row"]: saveRowHandler, ["Duplicate Row"]: duplicateRowHandler, @@ -318,6 +326,7 @@ const handlerMap = { ["Upload File to S3"]: s3UploadHandler, ["Export Data"]: exportDataHandler, ["Continue if / Stop if"]: continueIfHandler, + ["Show Notification"]: showNotificationHandler, } const confirmTextMap = { From 19c99f4390e88637dc3d579eda5895296c9cb1de Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 22 Aug 2022 11:08:52 +0100 Subject: [PATCH 08/17] Allow configuring whether notification is automatically dismissed or not --- .../actions/ShowNotification.svelte | 11 ++++++++--- packages/client/src/stores/notification.js | 12 ++++++++---- packages/client/src/utils/buttonActions.js | 4 ++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ShowNotification.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ShowNotification.svelte index ed4ecc2738..ca8e82ea73 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ShowNotification.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/ShowNotification.svelte @@ -1,5 +1,5 @@
- + (parameters.message = e.detail)} /> From 8236bb212753e9a9939c0c2b57dcb335943b3524 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 22 Aug 2022 11:15:43 +0100 Subject: [PATCH 10/17] fix qa nightly build --- packages/builder/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/package.json b/packages/builder/package.json index 569a6c1614..82b06224ed 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -17,7 +17,7 @@ "cy:run:ci:record": "xvfb-run cypress run --headed --browser chrome --record", "cy:test": "start-server-and-test cy:setup http://localhost:4100/builder cy:run", "cy:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci", - "cy:ci:record": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci:record && npm run cy:ci:report", + "cy:ci:record": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci:record; npm run cy:ci:report", "cy:ci:report": "mochawesome-merge cypress/reports/*.json > cypress/reports/testReport.json && marge cypress/reports/testReport.json --reportDir cypress/reports --inline", "cy:ci:notify": "node scripts/cypressResultsWebhook", "cy:debug": "start-server-and-test cy:setup http://localhost:4100/builder cy:open", @@ -121,4 +121,4 @@ "vite": "^2.1.5" }, "gitHead": "115189f72a850bfb52b65ec61d932531bf327072" -} +} \ No newline at end of file From 09d37fb36ff79836206638b29133518706753ffa Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 22 Aug 2022 11:18:24 +0100 Subject: [PATCH 11/17] generate report even if tests fail --- packages/builder/cypress/integration/createApp.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index 179741e21a..544824a963 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -34,7 +34,7 @@ filterTests(['smoke', 'all'], () => { } }) - cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist") + cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("not.exist") cy.get(interact.TEMPLATE_CATEGORY).should("exist") cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).its('length').should('be.gt', 1) From 3f661d06a9d402a9e48c972191affe614a9874a1 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 22 Aug 2022 12:01:50 +0100 Subject: [PATCH 12/17] enforce fail --- .github/workflows/smoke_test.yaml | 16 ++++++++++++++-- .../cypress/integration/createApp.spec.js | 3 ++- packages/builder/package.json | 4 ++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/smoke_test.yaml b/.github/workflows/smoke_test.yaml index 7002c8335b..cffb914aaf 100644 --- a/.github/workflows/smoke_test.yaml +++ b/.github/workflows/smoke_test.yaml @@ -1,4 +1,4 @@ -name: Budibase Smoke Test +name: Budibase Nightly Tests on: workflow_dispatch: @@ -6,7 +6,7 @@ on: - cron: "0 5 * * *" # every day at 5AM jobs: - release: + nightly: runs-on: ubuntu-latest steps: @@ -43,6 +43,18 @@ jobs: name: Test Reports path: packages/builder/cypress/reports/testReport.html + # TODO: enable once running in QA test env + # - name: Configure AWS Credentials + # uses: aws-actions/configure-aws-credentials@v1 + # with: + # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + # aws-region: eu-west-1 + + # - name: Upload test results HTML + # uses: aws-actions/configure-aws-credentials@v1 + # run: aws s3 cp packages/builder/cypress/reports/testReport.html s3://{{ secrets.BUDI_QA_REPORTS_BUCKET_NAME }}/$GITHUB_RUN_ID/index.html + - name: Cypress Discord Notify run: yarn test:e2e:ci:notify env: diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index 544824a963..7198088fb4 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -34,7 +34,8 @@ filterTests(['smoke', 'all'], () => { } }) - cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("not.exist") + cy.get(".thisisnothere").should("exist") + cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist") cy.get(interact.TEMPLATE_CATEGORY).should("exist") cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).its('length').should('be.gt', 1) diff --git a/packages/builder/package.json b/packages/builder/package.json index 82b06224ed..4f29ce36a4 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -13,8 +13,8 @@ "cy:setup:ci": "node ./cypress/setup.js", "cy:open": "cypress open", "cy:run": "cypress run", - "cy:run:ci": "cypress run --headed --browser chrome --spec cypress/integration/createApp.spec.js", - "cy:run:ci:record": "xvfb-run cypress run --headed --browser chrome --record", + "cy:run:ci": "cypress run --headed --browser chrome --spec cypress/integration/createApp.spec.js", + "cy:run:ci:record": "xvfb-run cypress run --headed --browser chrome --record --spec cypress/integration/createApp.spec.js", "cy:test": "start-server-and-test cy:setup http://localhost:4100/builder cy:run", "cy:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci", "cy:ci:record": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci:record; npm run cy:ci:report", From f95ea519a44857eb658e489e71bfa2c29400ed27 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 22 Aug 2022 12:34:40 +0100 Subject: [PATCH 13/17] more debug info --- packages/builder/scripts/cypressResultsWebhook.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/builder/scripts/cypressResultsWebhook.js b/packages/builder/scripts/cypressResultsWebhook.js index 457093e013..c22c46207d 100644 --- a/packages/builder/scripts/cypressResultsWebhook.js +++ b/packages/builder/scripts/cypressResultsWebhook.js @@ -114,7 +114,7 @@ async function discordCypressResultsNotification(report) { } const response = await fetch(WEBHOOK_URL, options) - if (response.status >= 400) { + if (response.status >= 201) { const text = await response.text() console.error( `Error sending discord webhook. \nStatus: ${response.status}. \nResponse Body: ${text}. \nRequest Body: ${options.body}` @@ -123,8 +123,12 @@ async function discordCypressResultsNotification(report) { } async function run() { - const report = await generateReport() - await discordCypressResultsNotification(report) + try { + const report = await generateReport() + await discordCypressResultsNotification(report) + } catch (err) { + console.error(err) + } } run() From 422c38fce76b370f7285a1f770cb77ebd722523e Mon Sep 17 00:00:00 2001 From: Dean Date: Mon, 22 Aug 2022 12:38:23 +0100 Subject: [PATCH 14/17] Minor updates --- packages/bbui/src/Tags/Tag.svelte | 3 +-- .../src/pages/builder/portal/manage/auth/index.svelte | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/bbui/src/Tags/Tag.svelte b/packages/bbui/src/Tags/Tag.svelte index 9c4cb6e583..f7089decdb 100644 --- a/packages/bbui/src/Tags/Tag.svelte +++ b/packages/bbui/src/Tags/Tag.svelte @@ -8,7 +8,6 @@ export let invalid = false export let disabled = false export let closable = false - export let onClick
{#if closable} - + {/if}
diff --git a/packages/builder/src/pages/builder/portal/manage/auth/index.svelte b/packages/builder/src/pages/builder/portal/manage/auth/index.svelte index fc56c2cdef..733d7eee92 100644 --- a/packages/builder/src/pages/builder/portal/manage/auth/index.svelte +++ b/packages/builder/src/pages/builder/portal/manage/auth/index.svelte @@ -31,6 +31,8 @@ OIDC: "oidc", } + const HasSpacesRegex = /[\\"\s]/ + // Some older google configs contain a manually specified value - retain the functionality to edit the field // When there is no value or we are in the cloud - prohibit editing the field, must use platform url to change $: googleCallbackUrl = undefined @@ -462,7 +464,7 @@ let update = scopesFields[0].inputText.trim() - if (/[\\"\s]/.test(update)) { + if (HasSpacesRegex.test(update)) { scopesFields[0].error = "Auth scopes cannot contain spaces, double quotes or backslashes" return @@ -475,13 +477,10 @@ return } else { scopesFields[0].error = null - } - - if (scopes.indexOf(update) == -1) { scopes.push(update) providers.oidc.config.configs[0]["scopes"] = scopes + scopesFields[0].inputText = null } - scopesFields[0].inputText = null } }} /> @@ -493,7 +492,7 @@ {#each providers.oidc.config.configs[0]["scopes"] || [...defaultScopes] as tag, idx} { + on:click={() => { let idxScopes = providers.oidc.config.configs[0]["scopes"] if (idxScopes.length == 1) { idxScopes.pop() From b9ffa534ca5a51be395ddc720bb1b0dae0c98f90 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 22 Aug 2022 13:15:03 +0100 Subject: [PATCH 15/17] post failure notification --- packages/builder/scripts/cypressResultsWebhook.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/builder/scripts/cypressResultsWebhook.js b/packages/builder/scripts/cypressResultsWebhook.js index c22c46207d..4de4c01cc7 100644 --- a/packages/builder/scripts/cypressResultsWebhook.js +++ b/packages/builder/scripts/cypressResultsWebhook.js @@ -5,7 +5,6 @@ const path = require("path") const fs = require("fs") const WEBHOOK_URL = process.env.CYPRESS_WEBHOOK_URL -const OUTCOME = process.env.CYPRESS_OUTCOME const DASHBOARD_URL = process.env.CYPRESS_DASHBOARD_URL const GIT_SHA = process.env.GITHUB_SHA const GITHUB_ACTIONS_RUN_URL = process.env.GITHUB_ACTIONS_RUN_URL @@ -35,6 +34,8 @@ async function discordCypressResultsNotification(report) { skipped, } = report.stats + const OUTCOME = failures > 0 ? "failure" : "success" + const options = { method: "POST", headers: { @@ -123,12 +124,8 @@ async function discordCypressResultsNotification(report) { } async function run() { - try { - const report = await generateReport() - await discordCypressResultsNotification(report) - } catch (err) { - console.error(err) - } + const report = await generateReport() + await discordCypressResultsNotification(report) } run() From a0f1a05d33f9e2f5f00666bef08697ab672f0292 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 22 Aug 2022 13:45:52 +0100 Subject: [PATCH 16/17] revert back to original cypress command --- packages/builder/cypress/integration/createApp.spec.js | 1 - packages/builder/package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index 7198088fb4..179741e21a 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -34,7 +34,6 @@ filterTests(['smoke', 'all'], () => { } }) - cy.get(".thisisnothere").should("exist") cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist") cy.get(interact.TEMPLATE_CATEGORY).should("exist") diff --git a/packages/builder/package.json b/packages/builder/package.json index 4f29ce36a4..42a62399b8 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -14,7 +14,7 @@ "cy:open": "cypress open", "cy:run": "cypress run", "cy:run:ci": "cypress run --headed --browser chrome --spec cypress/integration/createApp.spec.js", - "cy:run:ci:record": "xvfb-run cypress run --headed --browser chrome --record --spec cypress/integration/createApp.spec.js", + "cy:run:ci:record": "cypress run --browser chrome --record", "cy:test": "start-server-and-test cy:setup http://localhost:4100/builder cy:run", "cy:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci", "cy:ci:record": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci:record; npm run cy:ci:report", From 4d8b5e046fed6a0aa9ea91d0baf865abec88c4b8 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 22 Aug 2022 15:25:58 +0100 Subject: [PATCH 17/17] revert back to headed --- packages/builder/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/package.json b/packages/builder/package.json index 42a62399b8..53e0286ed1 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -14,7 +14,7 @@ "cy:open": "cypress open", "cy:run": "cypress run", "cy:run:ci": "cypress run --headed --browser chrome --spec cypress/integration/createApp.spec.js", - "cy:run:ci:record": "cypress run --browser chrome --record", + "cy:run:ci:record": "xvfb-run cypress run --headed --browser chrome --record", "cy:test": "start-server-and-test cy:setup http://localhost:4100/builder cy:run", "cy:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci", "cy:ci:record": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci:record; npm run cy:ci:report",