From e08e1a7b0dcc7c201f2780da0be217d7dc35afd9 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 6 Jan 2025 11:10:06 +0000 Subject: [PATCH 1/3] Convert portal OIDC store to TS --- packages/builder/src/stores/portal/oidc.js | 31 ---------------------- packages/builder/src/stores/portal/oidc.ts | 25 +++++++++++++++++ 2 files changed, 25 insertions(+), 31 deletions(-) delete mode 100644 packages/builder/src/stores/portal/oidc.js create mode 100644 packages/builder/src/stores/portal/oidc.ts diff --git a/packages/builder/src/stores/portal/oidc.js b/packages/builder/src/stores/portal/oidc.js deleted file mode 100644 index 65d8eac04c..0000000000 --- a/packages/builder/src/stores/portal/oidc.js +++ /dev/null @@ -1,31 +0,0 @@ -import { writable, get } from "svelte/store" -import { API } from "@/api" -import { auth } from "@/stores/portal" - -const OIDC_CONFIG = { - logo: undefined, - name: undefined, - uuid: undefined, -} - -export function createOidcStore() { - const store = writable(OIDC_CONFIG) - const { set, subscribe } = store - return { - subscribe, - set, - init: async () => { - const tenantId = get(auth).tenantId - const config = await API.getOIDCConfig(tenantId) - if (Object.keys(config || {}).length) { - // Just use the first config for now. - // We will be support multiple logins buttons later on. - set(...config) - } else { - set(OIDC_CONFIG) - } - }, - } -} - -export const oidc = createOidcStore() diff --git a/packages/builder/src/stores/portal/oidc.ts b/packages/builder/src/stores/portal/oidc.ts new file mode 100644 index 0000000000..a914645135 --- /dev/null +++ b/packages/builder/src/stores/portal/oidc.ts @@ -0,0 +1,25 @@ +import { get } from "svelte/store" +import { API } from "@/api" +import { auth } from "@/stores/portal" +import { BudiStore } from "../BudiStore" +import { PublicOIDCConfig } from "@budibase/types" + +class OIDCStore extends BudiStore { + constructor() { + super({}) + } + + async init() { + const tenantId = get(auth).tenantId + const config = await API.getOIDCConfig(tenantId) + if (Object.keys(config || {}).length) { + // Just use the first config for now. + // We will be support multiple logins buttons later on. + this.set(config[0]) + } else { + this.set({}) + } + } +} + +export const oidc = new OIDCStore() From 5d999b8e3a6add4a42718a34af3ee4d911584498 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 6 Jan 2025 11:53:21 +0000 Subject: [PATCH 2/3] Convert portal organisation store to TS --- .../builder/src/stores/portal/organisation.js | 66 ----------------- .../builder/src/stores/portal/organisation.ts | 71 +++++++++++++++++++ packages/types/src/documents/global/config.ts | 3 +- 3 files changed, 72 insertions(+), 68 deletions(-) delete mode 100644 packages/builder/src/stores/portal/organisation.js create mode 100644 packages/builder/src/stores/portal/organisation.ts diff --git a/packages/builder/src/stores/portal/organisation.js b/packages/builder/src/stores/portal/organisation.js deleted file mode 100644 index 6d41620c9f..0000000000 --- a/packages/builder/src/stores/portal/organisation.js +++ /dev/null @@ -1,66 +0,0 @@ -import { writable, get } from "svelte/store" -import { API } from "@/api" -import { auth } from "@/stores/portal" -import _ from "lodash" - -const DEFAULT_CONFIG = { - platformUrl: "", - logoUrl: undefined, - faviconUrl: undefined, - emailBrandingEnabled: true, - testimonialsEnabled: true, - platformTitle: "Budibase", - loginHeading: undefined, - loginButton: undefined, - metaDescription: undefined, - metaImageUrl: undefined, - metaTitle: undefined, - docsUrl: undefined, - company: "Budibase", - oidc: undefined, - google: undefined, - googleDatasourceConfigured: undefined, - oidcCallbackUrl: "", - googleCallbackUrl: "", - isSSOEnforced: false, - loaded: false, -} - -export function createOrganisationStore() { - const store = writable(DEFAULT_CONFIG) - const { subscribe, set } = store - - async function init() { - const tenantId = get(auth).tenantId - const settingsConfigDoc = await API.getTenantConfig(tenantId) - set({ ...DEFAULT_CONFIG, ...settingsConfigDoc.config, loaded: true }) - } - - async function save(config) { - // Delete non-persisted fields - const storeConfig = _.cloneDeep(get(store)) - delete storeConfig.oidc - delete storeConfig.google - delete storeConfig.googleDatasourceConfigured - delete storeConfig.oidcCallbackUrl - delete storeConfig.googleCallbackUrl - - // delete internal store field - delete storeConfig.loaded - - await API.saveConfig({ - type: "settings", - config: { ...storeConfig, ...config }, - }) - await init() - } - - return { - subscribe, - set, - save, - init, - } -} - -export const organisation = createOrganisationStore() diff --git a/packages/builder/src/stores/portal/organisation.ts b/packages/builder/src/stores/portal/organisation.ts new file mode 100644 index 0000000000..219245807a --- /dev/null +++ b/packages/builder/src/stores/portal/organisation.ts @@ -0,0 +1,71 @@ +import { get } from "svelte/store" +import { API } from "@/api" +import { auth } from "@/stores/portal" +import { + ConfigType, + PublicSettingsInnerConfig, + SettingsBrandingConfig, + SettingsInnerConfig, +} from "@budibase/types" +import { BudiStore } from "../BudiStore" + +interface LocalOrganisationState { + loaded: boolean +} + +type SavedOrganisationState = SettingsInnerConfig & SettingsBrandingConfig +type OrganisationState = SavedOrganisationState & + PublicSettingsInnerConfig & + LocalOrganisationState + +const DEFAULT_STATE: OrganisationState = { + platformUrl: "", + emailBrandingEnabled: true, + testimonialsEnabled: true, + platformTitle: "Budibase", + company: "Budibase", + google: false, + googleDatasourceConfigured: false, + oidc: false, + oidcCallbackUrl: "", + googleCallbackUrl: "", + loaded: false, +} + +class OrganisationStore extends BudiStore { + constructor() { + super(DEFAULT_STATE) + } + + async init() { + const tenantId = get(auth).tenantId + const settingsConfigDoc = await API.getTenantConfig(tenantId) + this.set({ ...DEFAULT_STATE, ...settingsConfigDoc.config, loaded: true }) + } + + async save(changes: Partial) { + // Strip non persisted fields + const { + oidc, + google, + googleDatasourceConfigured, + oidcCallbackUrl, + googleCallbackUrl, + loaded, + ...config + } = get(this.store) + + // Save new config + const newConfig: SavedOrganisationState = { + ...config, + ...changes, + } + await API.saveConfig({ + type: ConfigType.SETTINGS, + config: newConfig, + }) + await this.init() + } +} + +export const organisation = new OrganisationStore() diff --git a/packages/types/src/documents/global/config.ts b/packages/types/src/documents/global/config.ts index d51ca9d54d..1ad20e291f 100644 --- a/packages/types/src/documents/global/config.ts +++ b/packages/types/src/documents/global/config.ts @@ -26,13 +26,11 @@ export interface SMTPConfig extends Config {} export interface SettingsBrandingConfig { faviconUrl?: string faviconUrlEtag?: string - emailBrandingEnabled?: boolean testimonialsEnabled?: boolean platformTitle?: string loginHeading?: string loginButton?: string - metaDescription?: string metaImageUrl?: string metaTitle?: string @@ -42,6 +40,7 @@ export interface SettingsInnerConfig { platformUrl?: string company?: string logoUrl?: string // Populated on read + docsUrl?: string logoUrlEtag?: string uniqueTenantId?: string analyticsEnabled?: boolean From 41e3e2d77415d153c50679eb38e597fc09429ac5 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 8 Jan 2025 16:52:33 +0000 Subject: [PATCH 3/3] Improve handling of configs --- packages/builder/src/stores/portal/oidc.ts | 12 ++++-------- packages/frontend-core/src/api/configs.ts | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/builder/src/stores/portal/oidc.ts b/packages/builder/src/stores/portal/oidc.ts index a914645135..6c3609f9d5 100644 --- a/packages/builder/src/stores/portal/oidc.ts +++ b/packages/builder/src/stores/portal/oidc.ts @@ -11,14 +11,10 @@ class OIDCStore extends BudiStore { async init() { const tenantId = get(auth).tenantId - const config = await API.getOIDCConfig(tenantId) - if (Object.keys(config || {}).length) { - // Just use the first config for now. - // We will be support multiple logins buttons later on. - this.set(config[0]) - } else { - this.set({}) - } + const configs = await API.getOIDCConfigs(tenantId) + // Just use the first config for now. + // We will be support multiple logins buttons later on. + this.set(configs[0] || {}) } } diff --git a/packages/frontend-core/src/api/configs.ts b/packages/frontend-core/src/api/configs.ts index 82f08e58a7..408180a859 100644 --- a/packages/frontend-core/src/api/configs.ts +++ b/packages/frontend-core/src/api/configs.ts @@ -16,7 +16,7 @@ import { BaseAPIClient } from "./types" export interface ConfigEndpoints { getConfig: (type: ConfigType) => Promise getTenantConfig: (tentantId: string) => Promise - getOIDCConfig: (tenantId: string) => Promise + getOIDCConfigs: (tenantId: string) => Promise getOIDCLogos: () => Promise> saveConfig: (config: SaveConfigRequest) => Promise deleteConfig: (id: string, rev: string) => Promise @@ -73,7 +73,7 @@ export const buildConfigEndpoints = (API: BaseAPIClient): ConfigEndpoints => ({ * Gets the OIDC config for a certain tenant. * @param tenantId the tenant ID to get the config for */ - getOIDCConfig: async tenantId => { + getOIDCConfigs: async tenantId => { return await API.get({ url: `/api/global/configs/public/oidc?tenantId=${tenantId}`, })