improve structure of OIDC config
This commit is contained in:
parent
6c8a025760
commit
af792cc09e
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -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>
|
||||||
|
|
|
@ -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()}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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()
|
|
@ -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() {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in New Issue