improve structure of OIDC config

This commit is contained in:
Peter Clement 2021-07-13 14:54:20 +01:00
parent 6c8a025760
commit af792cc09e
9 changed files with 82 additions and 30 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -10,7 +10,7 @@
notifications, notifications,
} from "@budibase/bbui" } from "@budibase/bbui"
import { goto, params } from "@roxi/routify" import { goto, params } from "@roxi/routify"
import { auth, organisation } from "stores/portal" import { auth, organisation, oidc } from "stores/portal"
import GoogleButton from "./_components/GoogleButton.svelte" import GoogleButton from "./_components/GoogleButton.svelte"
import OIDCButton from "./_components/OIDCButton.svelte" import OIDCButton from "./_components/OIDCButton.svelte"
import Logo from "assets/bb-emblem.svg" import Logo from "assets/bb-emblem.svg"
@ -50,6 +50,7 @@
onMount(async () => { onMount(async () => {
await organisation.init() await organisation.init()
await oidc.init()
}) })
</script> </script>
@ -62,10 +63,7 @@
<Heading>Sign in to {company}</Heading> <Heading>Sign in to {company}</Heading>
</Layout> </Layout>
<GoogleButton /> <GoogleButton />
<OIDCButton <OIDCButton oidcIcon={$oidc.logo} oidcName={$oidc.name} />
oidcIcon={$organisation.oidcIcon}
oidcName={$organisation.oidcName}
/>
<Divider noGrid /> <Divider noGrid />
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
<Body size="S" textAlign="center">Sign in with email</Body> <Body size="S" textAlign="center">Sign in with email</Body>

View File

@ -2,7 +2,6 @@
import GoogleLogo from "./_logos/Google.svelte" import GoogleLogo from "./_logos/Google.svelte"
import OidcLogo from "./_logos/OIDC.svelte" import OidcLogo from "./_logos/OIDC.svelte"
import MicrosoftLogo from "assets/microsoft-logo.png" import MicrosoftLogo from "assets/microsoft-logo.png"
import OracleLogo from "assets/oracle-logo.png"
import Auth0Logo from "assets/auth0-logo.png" import Auth0Logo from "assets/auth0-logo.png"
import OidcLogoPng from "assets/oidc-logo.png" import OidcLogoPng from "assets/oidc-logo.png"
@ -19,14 +18,8 @@
} from "@budibase/bbui" } from "@budibase/bbui"
import { onMount } from "svelte" import { onMount } from "svelte"
import api from "builderStore/api" import api from "builderStore/api"
import { writable } from "svelte/store"
import { organisation } from "stores/portal" import { organisation } from "stores/portal"
const values = writable({
oidcIcon: $organisation.oidcIcon,
oidcName: $organisation.oidcName,
})
const ConfigTypes = { const ConfigTypes = {
Google: "google", Google: "google",
OIDC: "oidc", OIDC: "oidc",
@ -58,11 +51,10 @@
let iconDropdownOptions = [ let iconDropdownOptions = [
{ {
label: "Azure AD", label: "Microsoft",
value: "AD", value: "Microsoft",
icon: MicrosoftLogo, icon: MicrosoftLogo,
}, },
{ label: "Oracle", value: "Oracle", icon: OracleLogo },
{ label: "Auth0", value: "Auth0", icon: Auth0Logo }, { label: "Auth0", value: "Auth0", icon: Auth0Logo },
{ label: "OIDC", value: "Oidc", icon: OidcLogoPng }, { label: "OIDC", value: "Oidc", icon: OidcLogoPng },
@ -88,9 +80,8 @@
const onFileSelected = e => { const onFileSelected = e => {
let fileName = e.target.files[0].name let fileName = e.target.files[0].name
image = e.target.files[0] image = e.target.files[0]
$values.oidcIcon = fileName providers.oidc.config.configs[0].logo = fileName
iconDropdownOptions.unshift({ label: fileName, value: fileName }) iconDropdownOptions.unshift({ label: fileName, value: fileName })
image && uploadLogo(image)
} }
const providers = { google, oidc } const providers = { google, oidc }
@ -98,7 +89,6 @@
async function save(docs) { async function save(docs) {
// only if the user has provided an image, upload it. // only if the user has provided an image, upload it.
image && uploadLogo(image) image && uploadLogo(image)
await organisation.save($values)
let calls = [] let calls = []
docs.forEach(element => { docs.forEach(element => {
calls.push(api.post(`/api/admin/configs`, element)) calls.push(api.post(`/api/admin/configs`, element))
@ -164,7 +154,7 @@
if (!oidcDoc._id) { if (!oidcDoc._id) {
providers.oidc = { providers.oidc = {
type: ConfigTypes.OIDC, type: ConfigTypes.OIDC,
config: {}, config: { configs: [{}] },
} }
} else { } else {
providers.oidc = oidcDoc providers.oidc = oidcDoc
@ -194,7 +184,7 @@
To allow users to authenticate using their Google accounts, fill out the To allow users to authenticate using their Google accounts, fill out the
fields below. fields below.
</Body> </Body>
</Layout> </Layout>dddd
<Layout gap="XS" noPadding> <Layout gap="XS" noPadding>
{#each GoogleConfigFields.Google as field} {#each GoogleConfigFields.Google as field}
<div class="form-row"> <div class="form-row">
@ -221,7 +211,7 @@
{#each OIDCConfigFields.Oidc as field} {#each OIDCConfigFields.Oidc as field}
<div class="form-row"> <div class="form-row">
<Label size="L">{OIDCConfigLabels.Oidc[field]}</Label> <Label size="L">{OIDCConfigLabels.Oidc[field]}</Label>
<Input bind:value={providers.oidc.config[field]} /> <Input bind:value={providers.oidc.config.configs[0][field]} />
</div> </div>
{/each} {/each}
<br /> <br />
@ -230,13 +220,13 @@
</Body> </Body>
<div class="form-row"> <div class="form-row">
<Label size="L">Name</Label> <Label size="L">Name</Label>
<Input bind:value={$values.oidcName} /> <Input bind:value={providers.oidc.config.configs[0].name} />
</div> </div>
<div class="form-row"> <div class="form-row">
<Label size="L">Icon</Label> <Label size="L">Icon</Label>
<Select <Select
label="" label=""
bind:value={$values.oidcIcon} bind:value={providers.oidc.config.configs[0].logo}
options={iconDropdownOptions} options={iconDropdownOptions}
on:change={e => e.detail === "Upload" && fileinput.click()} on:change={e => e.detail === "Upload" && fileinput.click()}
/> />

View File

@ -4,3 +4,4 @@ export { admin } from "./admin"
export { apps } from "./apps" export { apps } from "./apps"
export { email } from "./email" export { email } from "./email"
export { auth } from "./auth" export { auth } from "./auth"
export { oidc } from "./oidc"

View File

@ -0,0 +1,32 @@
import { writable } from "svelte/store"
import api from "builderStore/api"
const OIDC_CONFIG = {
logo: undefined,
name: undefined,
}
export function createOidcStore() {
const store = writable(OIDC_CONFIG)
const { set, subscribe } = store
async function init() {
const res = await api.get(`/api/admin/configs/publicOidc`)
const json = await res.json()
if (json.status === 400) {
set(OIDC_CONFIG)
} else {
// Just use the first config for now. We will be support multiple logins buttons later on.
set(...json)
}
}
return {
subscribe,
set,
init,
}
}
export const oidc = createOidcStore()

View File

@ -6,8 +6,6 @@ const DEFAULT_CONFIG = {
logoUrl: undefined, logoUrl: undefined,
docsUrl: undefined, docsUrl: undefined,
company: "Budibase", company: "Budibase",
oidcIcon: undefined,
oidcName: undefined,
} }
export function createOrganisationStore() { export function createOrganisationStore() {

View File

@ -98,6 +98,30 @@ exports.find = async function (ctx) {
} }
} }
exports.publicOidc = async function (ctx) {
const db = new CouchDB(GLOBAL_DB)
try {
// Find the config with the most granular scope based on context
const oidcConfig = await getScopedFullConfig(db, {
type: Configs.OIDC,
})
if (!oidcConfig) {
ctx.body = {}
} else {
const partialOidcCofig = oidcConfig.config.configs.map(config => {
return {
logo: config.logo,
name: config.name,
}
})
ctx.body = partialOidcCofig
}
} catch (err) {
ctx.throw(err.status, err)
}
}
exports.publicSettings = async function (ctx) { exports.publicSettings = async function (ctx) {
const db = new CouchDB(GLOBAL_DB) const db = new CouchDB(GLOBAL_DB)
try { try {

View File

@ -49,6 +49,10 @@ const PUBLIC_ENDPOINTS = [
route: "/api/admin/configs/public", route: "/api/admin/configs/public",
method: "GET", method: "GET",
}, },
{
route: "/api/admin/configs/publicOidc",
method: "GET",
},
] ]
const router = new Router() const router = new Router()

View File

@ -44,11 +44,15 @@ function googleValidation() {
function oidcValidation() { function oidcValidation() {
// prettier-ignore // prettier-ignore
return Joi.object({ return Joi.object({
clientID: Joi.string().required(), configs: Joi.array().items(
clientSecret: Joi.string().required(), Joi.object({
configUrl: Joi.string().required(), clientID: Joi.string().required(),
iconName: Joi.string().optional(), clientSecret: Joi.string().required(),
name: Joi.string().optional(), configUrl: Joi.string().required(),
logo: Joi.string().optional(),
name: Joi.string().optional(),
})
).required(true)
}).unknown(true) }).unknown(true)
} }
@ -104,6 +108,7 @@ router
controller.fetch controller.fetch
) )
.get("/api/admin/configs/public", controller.publicSettings) .get("/api/admin/configs/public", controller.publicSettings)
.get("/api/admin/configs/publicOidc", controller.publicOidc)
.get("/api/admin/configs/:type", buildConfigGetValidation(), controller.find) .get("/api/admin/configs/:type", buildConfigGetValidation(), controller.find)
.post( .post(
"/api/admin/configs/upload/:type/:name", "/api/admin/configs/upload/:type/:name",