Updates to upgrade page to change config based on offlineMode value

This commit is contained in:
Rory Powell 2023-07-06 20:47:12 +01:00
parent efe53bb217
commit 1ba3665ed4
3 changed files with 201 additions and 72 deletions

View File

@ -10,6 +10,8 @@
Label,
ButtonGroup,
notifications,
CopyInput,
File
} from "@budibase/bbui"
import { auth, admin } from "stores/portal"
import { redirect } from "@roxi/routify"
@ -21,44 +23,122 @@
$: license = $auth.user.license
$: upgradeUrl = `${$admin.accountPortalUrl}/portal/upgrade`
// LICENSE KEY
$: activateDisabled = !licenseKey || licenseKeyDisabled
let licenseInfo
let licenseKeyDisabled = false
let licenseKeyType = "text"
let licenseKey = ""
let deleteLicenseKeyModal
// OFFLINE LICENSE
let installationIdentifier = undefined
let offlineLicense = undefined
const offlineLicenseExtensions = [
".txt",
]
// Make sure page can't be visited directly in cloud
$: {
if ($admin.cloud) {
$redirect("../../portal")
}
console.log({ offlineLicense })
}
const activate = async () => {
// LICENSE KEY
const getLicenseKey = async () => {
try {
await API.activateLicenseKey({ licenseKey })
await auth.getSelf()
await setLicenseInfo()
notifications.success("Successfully activated")
licenseKey = await API.getLicenseKey()
if (licenseKey) {
licenseKey = "**********************************************"
licenseKeyType = "password"
licenseKeyDisabled = true
activateDisabled = true
}
} catch (e) {
notifications.error(e.message)
console.error(e)
notifications.error("Error retrieving license key")
}
}
const destroy = async () => {
const activateLicenseKey = async () => {
try {
await API.activateLicenseKey({ licenseKey })
await auth.getSelf()
await getLicenseKey()
notifications.success("Successfully activated")
} catch (e) {
console.error(e)
notifications.error("Error activating license key")
}
}
const deleteLicenseKey = async () => {
try {
await API.deleteLicenseKey({ licenseKey })
await auth.getSelf()
await setLicenseInfo()
await getLicenseKey()
// reset the form
licenseKey = ""
licenseKeyDisabled = false
notifications.success("Successfully deleted")
notifications.success("Offline license removed")
} catch (e) {
notifications.error(e.message)
console.error(e)
notifications.error("Error deleting license key")
}
}
// OFFLINE LICENSE
const getOfflineLicense = async () => {
try {
const license = await API.getOfflineLicense()
if (license) {
offlineLicense = {
name: "license"
}
} else {
offlineLicense = undefined
}
} catch (e) {
console.error(e)
notifications.error("Error loading offline license")
}
}
async function activateOfflineLicense(offlineLicense) {
try {
await API.activateOfflineLicense({ offlineLicense })
await auth.getSelf()
await getOfflineLicense()
notifications.success("Successfully activated")
} catch (e) {
console.error(e)
notifications.error("Error activating offline license")
}
}
async function deleteOfflineLicense() {
try {
await API.deleteOfflineLicense()
await auth.getSelf()
await getOfflineLicense()
notifications.success("Successfully removed ofline license")
} catch (e) {
console.error(e)
notifications.error("Error upload offline license")
}
}
async function onOfflineLicenseChange(event) {
if (event.detail) {
const reader = new FileReader()
reader.readAsText(event.detail)
reader.onload = () => activateOfflineLicense(reader.result)
} else {
await deleteOfflineLicense()
}
}
@ -73,29 +153,19 @@
}
}
// deactivate the license key field if there is a license key set
$: {
if (licenseInfo?.licenseKey) {
licenseKey = "**********************************************"
licenseKeyType = "password"
licenseKeyDisabled = true
activateDisabled = true
}
}
const setLicenseInfo = async () => {
licenseInfo = await API.getLicenseInfo()
}
onMount(async () => {
await setLicenseInfo()
if ($admin.offlineMode) {
await getOfflineLicense()
} else {
await getLicenseKey()
}
})
</script>
{#if $auth.isAdmin}
<DeleteLicenseKeyModal
bind:this={deleteLicenseKeyModal}
onConfirm={destroy}
onConfirm={deleteLicenseKey}
/>
<Layout noPadding>
<Layout gap="XS" noPadding>
@ -112,38 +182,73 @@
</Body>
</Layout>
<Divider />
<Layout gap="XS" noPadding>
<Heading size="S">Activate</Heading>
<Body size="S">Enter your license key below to activate your plan</Body>
</Layout>
<Layout noPadding>
<div class="fields">
<div class="field">
<Label size="L">License key</Label>
<Input
thin
bind:value={licenseKey}
type={licenseKeyType}
disabled={licenseKeyDisabled}
{#if $admin.offlineMode}
<Layout gap="XS" noPadding>
<Heading size="XS">Installation identifier</Heading>
<Body size="S">Share this with support@budibase.com to obtain your offline license</Body>
</Layout>
<Layout noPadding>
<div class="fields">
<div class="field">
<CopyInput value={installationIdentifier} />
</div>
</div>
</Layout>
<Divider />
<Layout gap="XS" noPadding>
<Heading size="XS">License</Heading>
<Body size="S">Upload your license to activate your plan</Body>
</Layout>
<Layout noPadding>
<div>
<File
title="Upload license"
extensions={offlineLicenseExtensions}
value={offlineLicense}
on:change={onOfflineLicenseChange}
allowClear={true}
disabled={!!offlineLicense}
/>
</div>
</div>
<ButtonGroup gap="M">
<Button cta on:click={activate} disabled={activateDisabled}>
Activate
</Button>
{#if licenseInfo?.licenseKey}
<Button warning on:click={() => deleteLicenseKeyModal.show()}>
Delete
</Layout>
{:else}
<Layout gap="XS" noPadding>
<Heading size="XS">Activate</Heading>
<Body size="S">Enter your license key below to activate your plan</Body>
</Layout>
<Layout noPadding>
<div class="fields">
<div class="field">
<Label size="L">License key</Label>
<Input
thin
bind:value={licenseKey}
type={licenseKeyType}
disabled={licenseKeyDisabled}
/>
</div>
</div>
<ButtonGroup gap="M">
<Button cta on:click={activateLicenseKey} disabled={activateDisabled}>
Activate
</Button>
{/if}
</ButtonGroup>
</Layout>
{#if licenseKey}
<Button warning on:click={() => deleteLicenseKeyModal.show()}>
Delete
</Button>
{/if}
</ButtonGroup>
</Layout>
{/if}
<Divider />
<Layout gap="XS" noPadding>
<Heading size="S">Plan</Heading>
<Layout noPadding gap="XXS">
<Heading size="XS">Plan</Heading>
<Layout noPadding gap="S">
<Body size="S">You are currently on the {license.plan.type} plan</Body>
<div>
<Body size="S">If you purchase or update your plan on the account</Body>
<Body size="S">portal, click the refresh button to sync those changes</Body>
</div>
<Body size="XS">
{processStringSync("Updated {{ duration time 'millisecond' }} ago", {
time:

View File

@ -17,6 +17,7 @@ export const DEFAULT_CONFIG = {
adminUser: { checked: false },
sso: { checked: false },
},
offlineMode: false
}
export function createAdminStore() {

View File

@ -1,32 +1,56 @@
export const buildLicensingEndpoints = API => ({
/**
* Activates a self hosted license key
*/
// LICENSE KEY
activateLicenseKey: async data => {
return API.post({
url: `/api/global/license/activate`,
url: `/api/global/license/key`,
body: data,
})
},
/**
* Delete a self hosted license key
*/
deleteLicenseKey: async () => {
return API.delete({
url: `/api/global/license/info`,
url: `/api/global/license/key`,
})
},
getLicenseKey: async () => {
try {
return await API.get({
url: "/api/global/license/key",
})
} catch (e) {
if (e.status !== 404) {
throw e
}
}
},
/**
* Get the license info - metadata about the license including the
* obfuscated license key.
*/
getLicenseInfo: async () => {
return API.get({
url: "/api/global/license/info",
// OFFLINE LICENSE
activateOfflineLicense: async ({ offlineLicense }) => {
return API.post({
url: "/api/global/license/offline",
body: {
offlineLicense
},
})
},
deleteOfflineLicense: async () => {
return API.delete({
url: "/api/global/license/offline",
})
},
getOfflineLicense: async () => {
try {
return await API.get({
url: "/api/global/license/offline",
})
} catch (e) {
if (e.status !== 404) {
throw e
}
}
},
/**
* Refreshes the license cache
@ -36,7 +60,6 @@ export const buildLicensingEndpoints = API => ({
url: "/api/global/license/refresh",
})
},
/**
* Retrieve the usage information for the tenant
*/