Adding the ability to run the monorepo in cloud mode without the connected account portal (login, org setting and admin creation are all available again) as well as re-working how the redirects work to massively reduce the chance of cycles which I was experiencing constantly.

This commit is contained in:
mike12345567 2021-09-29 16:55:59 +01:00
parent 1f127939af
commit a0f69251c8
15 changed files with 59 additions and 27 deletions

View File

@ -12,7 +12,7 @@ const populateFromDB = async (userId, tenantId) => {
const user = await getGlobalDB(tenantId).get(userId) const user = await getGlobalDB(tenantId).get(userId)
user.budibaseAccess = true user.budibaseAccess = true
if (!env.SELF_HOSTED) { if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
const account = await accounts.getAccount(user.email) const account = await accounts.getAccount(user.email)
if (account) { if (account) {
user.account = account user.account = account

View File

@ -21,6 +21,7 @@ module.exports = {
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY, INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
MULTI_TENANCY: process.env.MULTI_TENANCY, MULTI_TENANCY: process.env.MULTI_TENANCY,
ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL, ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
SELF_HOSTED: !!parseInt(process.env.SELF_HOSTED), SELF_HOSTED: !!parseInt(process.env.SELF_HOSTED),
COOKIE_DOMAIN: process.env.COOKIE_DOMAIN, COOKIE_DOMAIN: process.env.COOKIE_DOMAIN,
isTest, isTest,

View File

@ -4,11 +4,13 @@
import { onMount } from "svelte" import { onMount } from "svelte"
let loaded = false let loaded = false
// don't react to these
let cloud = $admin.cloud
let shouldRedirect = !cloud || $admin.disableAccountPortal
$: multiTenancyEnabled = $admin.multiTenancy $: multiTenancyEnabled = $admin.multiTenancy
$: hasAdminUser = $admin?.checklist?.adminUser?.checked $: hasAdminUser = $admin?.checklist?.adminUser?.checked
$: tenantSet = $auth.tenantSet $: tenantSet = $auth.tenantSet
$: cloud = $admin.cloud
onMount(async () => { onMount(async () => {
await auth.checkAuth() await auth.checkAuth()
@ -18,30 +20,35 @@
$: { $: {
// We should never see the org or admin user creation screens in the cloud // We should never see the org or admin user creation screens in the cloud
if (!cloud) { const apiReady = $admin.loaded && $auth.loaded
const apiReady = $admin.loaded && $auth.loaded // if tenant is not set go to it
// if tenant is not set go to it
if (loaded && apiReady && multiTenancyEnabled && !tenantSet) {
$redirect("./auth/org")
}
// Force creation of an admin user if one doesn't exist
else if (loaded && apiReady && !hasAdminUser) {
$redirect("./admin")
}
}
}
// Redirect to log in at any time if the user isn't authenticated
$: {
if ( if (
loaded &&
shouldRedirect &&
apiReady &&
multiTenancyEnabled &&
!tenantSet
) {
$redirect("./auth/org")
}
// Force creation of an admin user if one doesn't exist
else if (loaded && shouldRedirect && apiReady && !hasAdminUser) {
$redirect("./admin")
}
// Redirect to log in at any time if the user isn't authenticated
else if (
loaded && loaded &&
(hasAdminUser || cloud) && (hasAdminUser || cloud) &&
!$auth.user && !$auth.user &&
!$isActive("./auth") && !$isActive("./auth") &&
!$isActive("./invite") !$isActive("./invite") &&
!$isActive("./admin")
) { ) {
const returnUrl = encodeURIComponent(window.location.pathname) const returnUrl = encodeURIComponent(window.location.pathname)
$redirect("./auth?", { returnUrl }) $redirect("./auth?", { returnUrl })
} else if ($auth?.user?.forceResetPassword) { }
// check if password reset required for user
else if ($auth.user?.forceResetPassword) {
$redirect("./auth/reset") $redirect("./auth/reset")
} }
} }

View File

@ -22,6 +22,7 @@
$: tenantId = $auth.tenantId $: tenantId = $auth.tenantId
$: multiTenancyEnabled = $admin.multiTenancy $: multiTenancyEnabled = $admin.multiTenancy
$: cloud = $admin.cloud
async function save() { async function save() {
try { try {
@ -72,7 +73,7 @@
> >
Change organisation Change organisation
</ActionButton> </ActionButton>
{:else} {:else if !cloud}
<ActionButton <ActionButton
quiet quiet
on:click={() => { on:click={() => {

View File

@ -15,6 +15,7 @@
if ( if (
!$auth.user && !$auth.user &&
$admin.cloud && $admin.cloud &&
!$admin.disableAccountPortal &&
$admin.accountPortalUrl && $admin.accountPortalUrl &&
!$admin?.checklist?.sso?.checked !$admin?.checklist?.sso?.checked
) { ) {

View File

@ -9,6 +9,7 @@
let tenantId = get(auth).tenantSet ? get(auth).tenantId : "" let tenantId = get(auth).tenantSet ? get(auth).tenantId : ""
$: multiTenancyEnabled = $admin.multiTenancy $: multiTenancyEnabled = $admin.multiTenancy
$: cloud = $admin.cloud $: cloud = $admin.cloud
$: disableAccountPortal = $admin.disableAccountPortal
async function setOrg() { async function setOrg() {
if (tenantId == null || tenantId === "") { if (tenantId == null || tenantId === "") {
@ -26,7 +27,7 @@
onMount(async () => { onMount(async () => {
await auth.checkQueryString() await auth.checkQueryString()
if (!multiTenancyEnabled || cloud) { if (!multiTenancyEnabled || (cloud && !disableAccountPortal)) {
$goto("../") $goto("../")
} else { } else {
admin.unload() admin.unload()

View File

@ -5,11 +5,9 @@
auth.checkQueryString() auth.checkQueryString()
$: { $: {
if (!$auth.user) { if ($auth.user?.builder?.global) {
$redirect(`./auth`)
} else if ($auth.user.builder?.global) {
$redirect(`./portal`) $redirect(`./portal`)
} else { } else if ($auth.user) {
$redirect(`./apps`) $redirect(`./apps`)
} }
} }

View File

@ -35,6 +35,7 @@
let unpublishModal let unpublishModal
let creatingApp = false let creatingApp = false
let loaded = false let loaded = false
let cloud = $admin.cloud
$: enrichedApps = enrichApps($apps, $auth.user, sortBy) $: enrichedApps = enrichApps($apps, $auth.user, sortBy)
@ -199,7 +200,9 @@
<div class="title"> <div class="title">
<Heading>Apps</Heading> <Heading>Apps</Heading>
<ButtonGroup> <ButtonGroup>
<Button secondary on:click={initiateAppsExport}>Export apps</Button> {#if cloud}
<Button secondary on:click={initiateAppsExport}>Export apps</Button>
{/if}
<Button secondary on:click={initiateAppImport}>Import app</Button> <Button secondary on:click={initiateAppImport}>Import app</Button>
<Button cta on:click={initiateAppCreation}>Create app</Button> <Button cta on:click={initiateAppCreation}>Create app</Button>
</ButtonGroup> </ButtonGroup>

View File

@ -7,6 +7,7 @@ export function createAdminStore() {
loaded: false, loaded: false,
multiTenancy: false, multiTenancy: false,
cloud: false, cloud: false,
disableAccountPortal: false,
accountPortalUrl: "", accountPortalUrl: "",
onboardingProgress: 0, onboardingProgress: 0,
checklist: { checklist: {
@ -47,12 +48,14 @@ export function createAdminStore() {
async function getEnvironment() { async function getEnvironment() {
let multiTenancyEnabled = false let multiTenancyEnabled = false
let cloud = false let cloud = false
let disableAccountPortal = false
let accountPortalUrl = "" let accountPortalUrl = ""
try { try {
const response = await api.get(`/api/system/environment`) const response = await api.get(`/api/system/environment`)
const json = await response.json() const json = await response.json()
multiTenancyEnabled = json.multiTenancy multiTenancyEnabled = json.multiTenancy
cloud = json.cloud cloud = json.cloud
disableAccountPortal = json.disableAccountPortal
accountPortalUrl = json.accountPortalUrl accountPortalUrl = json.accountPortalUrl
} catch (err) { } catch (err) {
// just let it stay disabled // just let it stay disabled
@ -60,6 +63,7 @@ export function createAdminStore() {
admin.update(store => { admin.update(store => {
store.multiTenancy = multiTenancyEnabled store.multiTenancy = multiTenancyEnabled
store.cloud = cloud store.cloud = cloud
store.disableAccountPortal = disableAccountPortal
store.accountPortalUrl = accountPortalUrl store.accountPortalUrl = accountPortalUrl
return store return store
}) })

View File

@ -48,6 +48,7 @@ async function init() {
COUCH_DB_PASSWORD: "budibase", COUCH_DB_PASSWORD: "budibase",
COUCH_DB_USER: "budibase", COUCH_DB_USER: "budibase",
SELF_HOSTED: 1, SELF_HOSTED: 1,
DISABLE_ACCOUNT_PORTAL: "",
MULTI_TENANCY: "", MULTI_TENANCY: "",
} }
let envFile = "" let envFile = ""

View File

@ -40,6 +40,7 @@ module.exports = {
NODE_ENV: process.env.NODE_ENV, NODE_ENV: process.env.NODE_ENV,
JEST_WORKER_ID: process.env.JEST_WORKER_ID, JEST_WORKER_ID: process.env.JEST_WORKER_ID,
BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT, BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT,
DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
// minor // minor
SALT_ROUNDS: process.env.SALT_ROUNDS, SALT_ROUNDS: process.env.SALT_ROUNDS,
LOGGER: process.env.LOGGER, LOGGER: process.env.LOGGER,

View File

@ -21,6 +21,7 @@ async function init() {
COUCH_DB_PASSWORD: "budibase", COUCH_DB_PASSWORD: "budibase",
// empty string is false // empty string is false
MULTI_TENANCY: "", MULTI_TENANCY: "",
DISABLE_ACCOUNT_PORTAL: "",
ACCOUNT_PORTAL_URL: "http://localhost:10001", ACCOUNT_PORTAL_URL: "http://localhost:10001",
} }
let envFile = "" let envFile = ""

View File

@ -65,7 +65,7 @@ async function saveUser(
} }
// check root account users in account portal // check root account users in account portal
if (!env.SELF_HOSTED) { if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
const account = await accounts.getAccount(email) const account = await accounts.getAccount(email)
if (account) { if (account) {
throw "Email address already in use." throw "Email address already in use."
@ -132,7 +132,7 @@ exports.save = async ctx => {
} }
const parseBooleanParam = param => { const parseBooleanParam = param => {
if (param && param == "false") { if (param && param === "false") {
return false return false
} else { } else {
return true return true
@ -160,6 +160,17 @@ exports.adminUser = async ctx => {
// write usage quotas for cloud // write usage quotas for cloud
if (!env.SELF_HOSTED) { if (!env.SELF_HOSTED) {
// could be a scenario where it exists, make sure its clean
try {
const usageQuota = await db.get(
StaticDatabases.PLATFORM_INFO.docs.usageQuota
)
if (usageQuota) {
await db.remove(usageQuota._id, usageQuota._rev)
}
} catch (err) {
// don't worry about errors
}
await db.post(generateNewUsageQuotaDoc()) await db.post(generateNewUsageQuotaDoc())
} }

View File

@ -5,5 +5,6 @@ exports.fetch = async ctx => {
multiTenancy: !!env.MULTI_TENANCY, multiTenancy: !!env.MULTI_TENANCY,
cloud: !env.SELF_HOSTED, cloud: !env.SELF_HOSTED,
accountPortalUrl: env.ACCOUNT_PORTAL_URL, accountPortalUrl: env.ACCOUNT_PORTAL_URL,
disableAccountPortal: env.DISABLE_ACCOUNT_PORTAL,
} }
} }

View File

@ -32,6 +32,7 @@ module.exports = {
REDIS_PASSWORD: process.env.REDIS_PASSWORD, REDIS_PASSWORD: process.env.REDIS_PASSWORD,
INTERNAL_API_KEY: process.env.INTERNAL_API_KEY, INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
MULTI_TENANCY: process.env.MULTI_TENANCY, MULTI_TENANCY: process.env.MULTI_TENANCY,
DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL, ACCOUNT_PORTAL_URL: process.env.ACCOUNT_PORTAL_URL,
SMTP_FALLBACK_ENABLED: process.env.SMTP_FALLBACK_ENABLED, SMTP_FALLBACK_ENABLED: process.env.SMTP_FALLBACK_ENABLED,
SMTP_USER: process.env.SMTP_USER, SMTP_USER: process.env.SMTP_USER,