General cleanup, doing away with the concept of hosting in the builder and the generally confusing difference between cloud, self hosting and running locally - server is simply always a server now.
This commit is contained in:
parent
c0d1f5ef8c
commit
2ec6b15e56
|
@ -14,3 +14,10 @@ exports.GlobalRoles = {
|
||||||
BUILDER: "builder",
|
BUILDER: "builder",
|
||||||
GROUP_MANAGER: "group_manager",
|
GROUP_MANAGER: "group_manager",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.Configs = {
|
||||||
|
SETTINGS: "settings",
|
||||||
|
ACCOUNT: "account",
|
||||||
|
SMTP: "smtp",
|
||||||
|
GOOGLE: "google",
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { writable } from "svelte/store"
|
||||||
import api, { get } from "../api"
|
import api, { get } from "../api"
|
||||||
|
|
||||||
const INITIAL_HOSTING_UI_STATE = {
|
const INITIAL_HOSTING_UI_STATE = {
|
||||||
hostingInfo: {},
|
|
||||||
appUrl: "",
|
appUrl: "",
|
||||||
deployedApps: {},
|
deployedApps: {},
|
||||||
deployedAppNames: [],
|
deployedAppNames: [],
|
||||||
|
@ -13,28 +12,12 @@ export const getHostingStore = () => {
|
||||||
const store = writable({ ...INITIAL_HOSTING_UI_STATE })
|
const store = writable({ ...INITIAL_HOSTING_UI_STATE })
|
||||||
store.actions = {
|
store.actions = {
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
const responses = await Promise.all([
|
const response = await api.get("/api/hosting/urls")
|
||||||
api.get("/api/hosting/"),
|
const urls = await response.json()
|
||||||
api.get("/api/hosting/urls"),
|
|
||||||
])
|
|
||||||
const [info, urls] = await Promise.all(responses.map(resp => resp.json()))
|
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
state.hostingInfo = info
|
|
||||||
state.appUrl = urls.app
|
state.appUrl = urls.app
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
return info
|
|
||||||
},
|
|
||||||
save: async hostingInfo => {
|
|
||||||
const response = await api.post("/api/hosting", hostingInfo)
|
|
||||||
const revision = (await response.json()).rev
|
|
||||||
store.update(state => {
|
|
||||||
state.hostingInfo = {
|
|
||||||
...hostingInfo,
|
|
||||||
_rev: revision,
|
|
||||||
}
|
|
||||||
return state
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
fetchDeployedApps: async () => {
|
fetchDeployedApps: async () => {
|
||||||
let deployments = await (await get("/api/hosting/apps")).json()
|
let deployments = await (await get("/api/hosting/apps")).json()
|
||||||
|
|
|
@ -36,8 +36,7 @@
|
||||||
let errorReason
|
let errorReason
|
||||||
let poll
|
let poll
|
||||||
let deployments = []
|
let deployments = []
|
||||||
let urlComponent =
|
let urlComponent = $store.url || `/${appId}`
|
||||||
$hostingStore.hostingInfo.type === "self" ? $store.url : `/${appId}`
|
|
||||||
let deploymentUrl = `${$hostingStore.appUrl}${urlComponent}`
|
let deploymentUrl = `${$hostingStore.appUrl}${urlComponent}`
|
||||||
|
|
||||||
const formatDate = (date, format) =>
|
const formatDate = (date, format) =>
|
||||||
|
|
|
@ -49,8 +49,6 @@
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const nameError = "Your application must have a name.",
|
const nameError = "Your application must have a name.",
|
||||||
urlError = "Your application must have a URL."
|
urlError = "Your application must have a URL."
|
||||||
let hostingInfo = await hostingStore.actions.fetch()
|
|
||||||
if (hostingInfo.type === "self") {
|
|
||||||
await hostingStore.actions.fetchDeployedApps()
|
await hostingStore.actions.fetchDeployedApps()
|
||||||
const existingAppNames = get(hostingStore).deployedAppNames
|
const existingAppNames = get(hostingStore).deployedAppNames
|
||||||
const existingAppUrls = get(hostingStore).deployedAppUrls
|
const existingAppUrls = get(hostingStore).deployedAppUrls
|
||||||
|
@ -68,9 +66,6 @@
|
||||||
urlValidation = {
|
urlValidation = {
|
||||||
url: string().required(urlError).notOneOf(existingAppUrls),
|
url: string().required(urlError).notOneOf(existingAppUrls),
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
nameValidation = { name: string().required(nameError) }
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -81,14 +76,12 @@
|
||||||
error={nameError}
|
error={nameError}
|
||||||
label="App Name"
|
label="App Name"
|
||||||
/>
|
/>
|
||||||
{#if $hostingStore.hostingInfo.type === "self"}
|
|
||||||
<Input
|
<Input
|
||||||
on:change={e => updateApplication({ url: e.detail })}
|
on:change={e => updateApplication({ url: e.detail })}
|
||||||
value={$store.url}
|
value={$store.url}
|
||||||
error={urlError}
|
error={urlError}
|
||||||
label="App URL"
|
label="App URL"
|
||||||
/>
|
/>
|
||||||
{/if}
|
|
||||||
<TextArea
|
<TextArea
|
||||||
on:change={e => updateApplication({ description: e.detail })}
|
on:change={e => updateApplication({ description: e.detail })}
|
||||||
value={$store.description}
|
value={$store.description}
|
||||||
|
|
|
@ -1,47 +1,19 @@
|
||||||
<script>
|
<script>
|
||||||
import { hostingStore } from "builderStore"
|
|
||||||
import { HostingTypes } from "constants/backend"
|
|
||||||
import {
|
import {
|
||||||
Heading,
|
Heading,
|
||||||
Divider,
|
Divider,
|
||||||
notifications,
|
notifications,
|
||||||
Input,
|
|
||||||
ModalContent,
|
ModalContent,
|
||||||
Toggle,
|
Toggle,
|
||||||
Body,
|
Body,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import ThemeEditor from "components/settings/ThemeEditor.svelte"
|
import ThemeEditor from "components/settings/ThemeEditor.svelte"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
import { onMount } from "svelte"
|
|
||||||
|
|
||||||
let hostingInfo
|
|
||||||
let selfhosted = false
|
|
||||||
|
|
||||||
$: analyticsDisabled = analytics.disabled()
|
$: analyticsDisabled = analytics.disabled()
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
hostingInfo.type = selfhosted ? HostingTypes.SELF : HostingTypes.CLOUD
|
|
||||||
if (!selfhosted && hostingInfo._rev) {
|
|
||||||
hostingInfo = {
|
|
||||||
type: hostingInfo.type,
|
|
||||||
_id: hostingInfo._id,
|
|
||||||
_rev: hostingInfo._rev,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await hostingStore.actions.save(hostingInfo)
|
|
||||||
notifications.success(`Settings saved.`)
|
notifications.success(`Settings saved.`)
|
||||||
} catch (err) {
|
|
||||||
notifications.error(`Failed to update builder settings.`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSelfHosting(event) {
|
|
||||||
if (hostingInfo.type === HostingTypes.CLOUD && event.detail) {
|
|
||||||
hostingInfo.hostingUrl = "localhost:10000"
|
|
||||||
hostingInfo.useHttps = false
|
|
||||||
hostingInfo.selfHostKey = "budibase"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleAnalytics() {
|
function toggleAnalytics() {
|
||||||
|
@ -51,33 +23,12 @@
|
||||||
analytics.optOut()
|
analytics.optOut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
hostingInfo = await hostingStore.actions.fetch()
|
|
||||||
selfhosted = hostingInfo.type === "self"
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModalContent title="Builder settings" confirmText="Save" onConfirm={save}>
|
<ModalContent title="Builder settings" confirmText="Save" onConfirm={save}>
|
||||||
<Heading size="XS">Theme</Heading>
|
<Heading size="XS">Theme</Heading>
|
||||||
<ThemeEditor />
|
<ThemeEditor />
|
||||||
<Divider noMargin noGrid />
|
<Divider noMargin noGrid />
|
||||||
<Heading size="XS">Hosting</Heading>
|
|
||||||
<Body size="S">
|
|
||||||
This section contains settings that relate to the deployment and hosting of
|
|
||||||
apps made in this builder.
|
|
||||||
</Body>
|
|
||||||
<Toggle
|
|
||||||
text="Self hosted"
|
|
||||||
on:change={updateSelfHosting}
|
|
||||||
bind:value={selfhosted}
|
|
||||||
/>
|
|
||||||
{#if selfhosted}
|
|
||||||
<Input bind:value={hostingInfo.hostingUrl} label="Hosting URL" />
|
|
||||||
<Input bind:value={hostingInfo.selfHostKey} label="Hosting Key" />
|
|
||||||
<Toggle text="HTTPS" bind:value={hostingInfo.useHttps} />
|
|
||||||
{/if}
|
|
||||||
<Divider noMargin noGrid />
|
|
||||||
<Heading size="XS">Analytics</Heading>
|
<Heading size="XS">Analytics</Heading>
|
||||||
<Body size="S">
|
<Body size="S">
|
||||||
If you would like to send analytics that help us make budibase better,
|
If you would like to send analytics that help us make budibase better,
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
import Spinner from "components/common/Spinner.svelte"
|
import Spinner from "components/common/Spinner.svelte"
|
||||||
import { Info, User } from "./Steps"
|
import { Info, User } from "./Steps"
|
||||||
import Indicator from "./Indicator.svelte"
|
import Indicator from "./Indicator.svelte"
|
||||||
import { goto } from "@roxi/routify"
|
|
||||||
import { fade } from "svelte/transition"
|
|
||||||
import { post } from "builderStore/api"
|
import { post } from "builderStore/api"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
@ -38,8 +36,6 @@
|
||||||
$: checkValidity($values, validators[$currentStep])
|
$: checkValidity($values, validators[$currentStep])
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const hostingInfo = await hostingStore.actions.fetch()
|
|
||||||
if (hostingInfo.type === "self") {
|
|
||||||
await hostingStore.actions.fetchDeployedApps()
|
await hostingStore.actions.fetchDeployedApps()
|
||||||
const existingAppNames = svelteGet(hostingStore).deployedAppNames
|
const existingAppNames = svelteGet(hostingStore).deployedAppNames
|
||||||
validators[0].applicationName = string()
|
validators[0].applicationName = string()
|
||||||
|
@ -52,7 +48,6 @@
|
||||||
appName => appName.toLowerCase() === value.toLowerCase()
|
appName => appName.toLowerCase() === value.toLowerCase()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const checkValidity = async (values, validator) => {
|
const checkValidity = async (values, validator) => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { Button, Modal, notifications, Heading } from "@budibase/bbui"
|
import { Button, Modal, notifications, Heading } from "@budibase/bbui"
|
||||||
import { store, hostingStore } from "builderStore"
|
import { store } from "builderStore"
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import DeploymentHistory from "components/deploy/DeploymentHistory.svelte"
|
import DeploymentHistory from "components/deploy/DeploymentHistory.svelte"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
@ -15,18 +15,6 @@
|
||||||
$: appId = $store.appId
|
$: appId = $store.appId
|
||||||
|
|
||||||
async function deployApp() {
|
async function deployApp() {
|
||||||
// Must have cloud or self host API key to deploy
|
|
||||||
if (!$hostingStore.hostingInfo?.selfHostKey) {
|
|
||||||
const response = await api.get(`/api/keys/`)
|
|
||||||
const userKeys = await response.json()
|
|
||||||
if (!userKeys.budibase) {
|
|
||||||
notifications.error(
|
|
||||||
"No budibase API Keys configured. You must set either a self hosted or cloud API key to deploy your budibase app."
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEPLOY_URL = `/api/deploy`
|
const DEPLOY_URL = `/api/deploy`
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -37,19 +25,10 @@
|
||||||
throw new Error()
|
throw new Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
analytics.captureEvent("Deployed App", {
|
|
||||||
appId,
|
|
||||||
hostingType: $hostingStore.hostingInfo?.type,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (analytics.requestFeedbackOnDeploy()) {
|
if (analytics.requestFeedbackOnDeploy()) {
|
||||||
feedbackModal.show()
|
feedbackModal.show()
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
analytics.captureEvent("Deploy App Failed", {
|
|
||||||
appId,
|
|
||||||
hostingType: $hostingStore.hostingInfo?.type,
|
|
||||||
})
|
|
||||||
analytics.captureException(err)
|
analytics.captureException(err)
|
||||||
notifications.error("Deployment unsuccessful. Please try again later.")
|
notifications.error("Deployment unsuccessful. Please try again later.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ const { cloneDeep } = require("lodash/fp")
|
||||||
const { processObject } = require("@budibase/string-templates")
|
const { processObject } = require("@budibase/string-templates")
|
||||||
const { getAllApps } = require("../../utilities")
|
const { getAllApps } = require("../../utilities")
|
||||||
const { USERS_TABLE_SCHEMA } = require("../../constants")
|
const { USERS_TABLE_SCHEMA } = require("../../constants")
|
||||||
const { getDeployedApps } = require("../../utilities/builder/hosting")
|
const { getDeployedApps } = require("../../utilities/workerRequests")
|
||||||
const { clientLibraryPath } = require("../../utilities")
|
const { clientLibraryPath } = require("../../utilities")
|
||||||
|
|
||||||
const URL_REGEX_SLASH = /\/|\\/g
|
const URL_REGEX_SLASH = /\/|\\/g
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const { getAppQuota } = require("./quota")
|
|
||||||
const env = require("../../../environment")
|
|
||||||
const newid = require("../../../db/newid")
|
const newid = require("../../../db/newid")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,24 +9,6 @@ class Deployment {
|
||||||
this._id = id || newid()
|
this._id = id || newid()
|
||||||
}
|
}
|
||||||
|
|
||||||
// purely so that we can do quota stuff outside the main deployment context
|
|
||||||
async init() {
|
|
||||||
if (!env.SELF_HOSTED) {
|
|
||||||
this.setQuota(await getAppQuota(this.appId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setQuota(quota) {
|
|
||||||
if (!quota) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.quota = quota
|
|
||||||
}
|
|
||||||
|
|
||||||
getQuota() {
|
|
||||||
return this.quota
|
|
||||||
}
|
|
||||||
|
|
||||||
getAppId() {
|
getAppId() {
|
||||||
return this.appId
|
return this.appId
|
||||||
}
|
}
|
||||||
|
@ -38,9 +18,6 @@ class Deployment {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.verification = verification
|
this.verification = verification
|
||||||
if (this.verification.quota) {
|
|
||||||
this.quota = this.verification.quota
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getVerification() {
|
getVerification() {
|
||||||
|
@ -58,9 +35,6 @@ class Deployment {
|
||||||
if (json.verification) {
|
if (json.verification) {
|
||||||
this.setVerification(json.verification)
|
this.setVerification(json.verification)
|
||||||
}
|
}
|
||||||
if (json.quota) {
|
|
||||||
this.setQuota(json.quota)
|
|
||||||
}
|
|
||||||
if (json.status) {
|
if (json.status) {
|
||||||
this.setStatus(json.status, json.err)
|
this.setStatus(json.status, json.err)
|
||||||
}
|
}
|
||||||
|
@ -78,9 +52,6 @@ class Deployment {
|
||||||
if (this.verification && this.verification.cfDistribution) {
|
if (this.verification && this.verification.cfDistribution) {
|
||||||
obj.cfDistribution = this.verification.cfDistribution
|
obj.cfDistribution = this.verification.cfDistribution
|
||||||
}
|
}
|
||||||
if (this.quota) {
|
|
||||||
obj.quota = this.quota
|
|
||||||
}
|
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,11 +58,6 @@ async function storeLocalDeploymentHistory(deployment) {
|
||||||
async function deployApp(deployment) {
|
async function deployApp(deployment) {
|
||||||
const appId = deployment.getAppId()
|
const appId = deployment.getAppId()
|
||||||
try {
|
try {
|
||||||
await deployment.init()
|
|
||||||
deployment.setVerification(
|
|
||||||
await deploymentService.preDeployment(deployment)
|
|
||||||
)
|
|
||||||
|
|
||||||
console.log(`Uploading assets for appID ${appId}..`)
|
console.log(`Uploading assets for appID ${appId}..`)
|
||||||
|
|
||||||
await deploymentService.deploy(deployment)
|
await deploymentService.deploy(deployment)
|
||||||
|
@ -71,8 +66,6 @@ async function deployApp(deployment) {
|
||||||
console.log("Replicating local PouchDB to CouchDB..")
|
console.log("Replicating local PouchDB to CouchDB..")
|
||||||
await deploymentService.replicateDb(deployment)
|
await deploymentService.replicateDb(deployment)
|
||||||
|
|
||||||
await deploymentService.postDeployment(deployment)
|
|
||||||
|
|
||||||
deployment.setStatus(DeploymentStatus.SUCCESS)
|
deployment.setStatus(DeploymentStatus.SUCCESS)
|
||||||
await storeLocalDeploymentHistory(deployment)
|
await storeLocalDeploymentHistory(deployment)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
const PouchDB = require("../../../db")
|
|
||||||
const {
|
|
||||||
DocumentTypes,
|
|
||||||
SEPARATOR,
|
|
||||||
UNICODE_MAX,
|
|
||||||
ViewNames,
|
|
||||||
} = require("../../../db/utils")
|
|
||||||
|
|
||||||
exports.getAppQuota = async function (appId) {
|
|
||||||
const db = new PouchDB(appId)
|
|
||||||
|
|
||||||
const rows = await db.allDocs({
|
|
||||||
startkey: DocumentTypes.ROW + SEPARATOR,
|
|
||||||
endkey: DocumentTypes.ROW + SEPARATOR + UNICODE_MAX,
|
|
||||||
})
|
|
||||||
|
|
||||||
const users = await db.allDocs({
|
|
||||||
startkey: DocumentTypes.USER + SEPARATOR,
|
|
||||||
endkey: DocumentTypes.USER + SEPARATOR + UNICODE_MAX,
|
|
||||||
})
|
|
||||||
|
|
||||||
const existingRows = rows.rows.length
|
|
||||||
const existingUsers = users.rows.length
|
|
||||||
|
|
||||||
const designDoc = await db.get("_design/database")
|
|
||||||
|
|
||||||
let views = 0
|
|
||||||
for (let viewName of Object.keys(designDoc.views)) {
|
|
||||||
if (Object.values(ViewNames).indexOf(viewName) === -1) {
|
|
||||||
views++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: existingRows,
|
|
||||||
users: existingUsers,
|
|
||||||
views: views,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +1,7 @@
|
||||||
const AWS = require("aws-sdk")
|
|
||||||
const {
|
const {
|
||||||
deployToObjectStore,
|
deployToObjectStore,
|
||||||
performReplication,
|
performReplication,
|
||||||
fetchCredentials,
|
|
||||||
} = require("./utils")
|
} = require("./utils")
|
||||||
const {
|
|
||||||
getWorkerUrl,
|
|
||||||
getCouchUrl,
|
|
||||||
getSelfHostKey,
|
|
||||||
} = require("../../../utilities/builder/hosting")
|
|
||||||
|
|
||||||
exports.preDeployment = async function () {
|
|
||||||
const url = `${await getWorkerUrl()}/api/deploy`
|
|
||||||
try {
|
|
||||||
const json = await fetchCredentials(url, {
|
|
||||||
selfHostKey: await getSelfHostKey(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// response contains:
|
|
||||||
// couchDbSession, bucket, objectStoreSession
|
|
||||||
|
|
||||||
// set credentials here, means any time we're verified we're ready to go
|
|
||||||
if (json.objectStoreSession) {
|
|
||||||
AWS.config.update({
|
|
||||||
accessKeyId: json.objectStoreSession.accessKeyId,
|
|
||||||
secretAccessKey: json.objectStoreSession.secretAccessKey,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return json
|
|
||||||
} catch (err) {
|
|
||||||
throw {
|
|
||||||
message: "Unauthorised to deploy, check self hosting key",
|
|
||||||
status: 401,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.postDeployment = async function () {
|
|
||||||
// we don't actively need to do anything after deployment in self hosting
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.deploy = async function (deployment) {
|
exports.deploy = async function (deployment) {
|
||||||
const appId = deployment.getAppId()
|
const appId = deployment.getAppId()
|
||||||
|
|
|
@ -1,41 +1,19 @@
|
||||||
const CouchDB = require("../../db")
|
const CouchDB = require("../../db")
|
||||||
const {
|
const { getDeployedApps } = require("../../utilities/workerRequests")
|
||||||
getHostingInfo,
|
const { getScopedConfig } = require("@budibase/auth").db
|
||||||
getDeployedApps,
|
const { Configs } = require("@budibase/auth").constants
|
||||||
HostingTypes,
|
const { checkSlashesInUrl } = require("../../utilities")
|
||||||
getAppUrl,
|
|
||||||
} = require("../../utilities/builder/hosting")
|
|
||||||
const { StaticDatabases } = require("../../db/utils")
|
|
||||||
|
|
||||||
exports.fetchInfo = async ctx => {
|
|
||||||
ctx.body = {
|
|
||||||
types: Object.values(HostingTypes),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.save = async ctx => {
|
|
||||||
const db = new CouchDB(StaticDatabases.BUILDER_HOSTING.name)
|
|
||||||
const { type } = ctx.request.body
|
|
||||||
if (type === HostingTypes.CLOUD && ctx.request.body._rev) {
|
|
||||||
ctx.body = await db.remove({
|
|
||||||
...ctx.request.body,
|
|
||||||
_id: StaticDatabases.BUILDER_HOSTING.baseDoc,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
ctx.body = await db.put({
|
|
||||||
...ctx.request.body,
|
|
||||||
_id: StaticDatabases.BUILDER_HOSTING.baseDoc,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.fetch = async ctx => {
|
|
||||||
ctx.body = await getHostingInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.fetchUrls = async ctx => {
|
exports.fetchUrls = async ctx => {
|
||||||
|
const appId = ctx.appId
|
||||||
|
const db = new CouchDB(appId)
|
||||||
|
const settings = await getScopedConfig(db, { type: Configs.SETTINGS })
|
||||||
|
let appUrl = "http://localhost:10000/app"
|
||||||
|
if (settings && settings["platformUrl"]) {
|
||||||
|
appUrl = checkSlashesInUrl(`${settings["platformUrl"]}/app`)
|
||||||
|
}
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
app: await getAppUrl(ctx.appId),
|
app: appUrl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,16 @@ class ScriptExecutor {
|
||||||
}
|
}
|
||||||
|
|
||||||
execute() {
|
execute() {
|
||||||
const returnValue = this.script.runInContext(this.context)
|
return this.script.runInContext(this.context)
|
||||||
return returnValue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.execute = async function (ctx) {
|
exports.execute = async function (ctx) {
|
||||||
const executor = new ScriptExecutor(ctx.request.body)
|
const executor = new ScriptExecutor(ctx.request.body)
|
||||||
|
|
||||||
const result = executor.execute()
|
ctx.body = executor.execute()
|
||||||
ctx.body = result
|
}
|
||||||
|
|
||||||
|
exports.save = async function(ctx) {
|
||||||
|
ctx.throw(501, "Not currently implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ const { ObjectStoreBuckets } = require("../../../constants")
|
||||||
const { prepareUpload } = require("../deploy/utils")
|
const { prepareUpload } = require("../deploy/utils")
|
||||||
const { processString } = require("@budibase/string-templates")
|
const { processString } = require("@budibase/string-templates")
|
||||||
const { budibaseTempDir } = require("../../../utilities/budibaseDir")
|
const { budibaseTempDir } = require("../../../utilities/budibaseDir")
|
||||||
const { getDeployedApps } = require("../../../utilities/builder/hosting")
|
const { getDeployedApps } = require("../../../utilities/workerRequests")
|
||||||
const CouchDB = require("../../../db")
|
const CouchDB = require("../../../db")
|
||||||
const {
|
const {
|
||||||
loadHandlebarsFile,
|
loadHandlebarsFile,
|
||||||
|
|
|
@ -7,10 +7,7 @@ const { BUILDER } = require("../../utilities/security/permissions")
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
router
|
router
|
||||||
.get("/api/hosting/info", authorized(BUILDER), controller.fetchInfo)
|
|
||||||
.get("/api/hosting/urls", authorized(BUILDER), controller.fetchUrls)
|
.get("/api/hosting/urls", authorized(BUILDER), controller.fetchUrls)
|
||||||
.get("/api/hosting", authorized(BUILDER), controller.fetch)
|
|
||||||
.post("/api/hosting", authorized(BUILDER), controller.save)
|
|
||||||
// this isn't risky, doesn't return anything about apps other than names and URLs
|
// this isn't risky, doesn't return anything about apps other than names and URLs
|
||||||
.get("/api/hosting/apps", selfhost, controller.getDeployedApps)
|
.get("/api/hosting/apps", selfhost, controller.getDeployedApps)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const Router = require("@koa/router")
|
const Router = require("@koa/router")
|
||||||
const controller = require("../controllers/hosting")
|
const controller = require("../controllers/script")
|
||||||
const authorized = require("../../middleware/authorized")
|
const authorized = require("../../middleware/authorized")
|
||||||
const { BUILDER } = require("../../utilities/security/permissions")
|
const { BUILDER } = require("../../utilities/security/permissions")
|
||||||
|
|
||||||
|
|
|
@ -15,25 +15,6 @@ describe("/hosting", () => {
|
||||||
app = await config.init()
|
app = await config.init()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("fetchInfo", () => {
|
|
||||||
it("should be able to fetch hosting information", async () => {
|
|
||||||
const res = await request
|
|
||||||
.get(`/api/hosting/info`)
|
|
||||||
.set(config.defaultHeaders())
|
|
||||||
.expect("Content-Type", /json/)
|
|
||||||
.expect(200)
|
|
||||||
expect(res.body).toEqual({ types: ["cloud", "self"]})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
|
||||||
await checkBuilderEndpoint({
|
|
||||||
config,
|
|
||||||
method: "GET",
|
|
||||||
url: `/api/hosting/info`,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("fetchUrls", () => {
|
describe("fetchUrls", () => {
|
||||||
it("should be able to fetch current app URLs", async () => {
|
it("should be able to fetch current app URLs", async () => {
|
||||||
const res = await request
|
const res = await request
|
||||||
|
@ -41,7 +22,7 @@ describe("/hosting", () => {
|
||||||
.set(config.defaultHeaders())
|
.set(config.defaultHeaders())
|
||||||
.expect("Content-Type", /json/)
|
.expect("Content-Type", /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
expect(res.body.app).toEqual(`https://${config.getAppId()}.app.budi.live`)
|
expect(res.body.app).toEqual(`http://localhost:10000/app`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
it("should apply authorization to endpoint", async () => {
|
||||||
|
@ -52,78 +33,4 @@ describe("/hosting", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("fetch", () => {
|
|
||||||
it("should be able to fetch the current hosting information", async () => {
|
|
||||||
const res = await request
|
|
||||||
.get(`/api/hosting`)
|
|
||||||
.set(config.defaultHeaders())
|
|
||||||
.expect("Content-Type", /json/)
|
|
||||||
.expect(200)
|
|
||||||
expect(res.body._id).toBeDefined()
|
|
||||||
expect(res.body.hostingUrl).toBeDefined()
|
|
||||||
expect(res.body.type).toEqual("cloud")
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
|
||||||
await checkBuilderEndpoint({
|
|
||||||
config,
|
|
||||||
method: "GET",
|
|
||||||
url: `/api/hosting`,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("save", () => {
|
|
||||||
it("should be able to update the hosting information", async () => {
|
|
||||||
const res = await request
|
|
||||||
.post(`/api/hosting`)
|
|
||||||
.send({
|
|
||||||
type: "self",
|
|
||||||
selfHostKey: "budibase",
|
|
||||||
hostingUrl: "localhost:10000",
|
|
||||||
useHttps: false,
|
|
||||||
})
|
|
||||||
.set(config.defaultHeaders())
|
|
||||||
.expect("Content-Type", /json/)
|
|
||||||
.expect(200)
|
|
||||||
expect(res.body.ok).toEqual(true)
|
|
||||||
// make sure URL updated
|
|
||||||
const urlRes = await request
|
|
||||||
.get(`/api/hosting/urls`)
|
|
||||||
.set(config.defaultHeaders())
|
|
||||||
.expect("Content-Type", /json/)
|
|
||||||
.expect(200)
|
|
||||||
expect(urlRes.body.app).toEqual(`http://localhost:10000/app`)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
|
||||||
await checkBuilderEndpoint({
|
|
||||||
config,
|
|
||||||
method: "POST",
|
|
||||||
url: `/api/hosting`,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("getDeployedApps", () => {
|
|
||||||
it("should fail when not self hosted", async () => {
|
|
||||||
await request
|
|
||||||
.get(`/api/hosting/apps`)
|
|
||||||
.set(config.defaultHeaders())
|
|
||||||
.expect("Content-Type", /json/)
|
|
||||||
.expect(400)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should get apps when in cloud", async () => {
|
|
||||||
await setup.switchToSelfHosted(async () => {
|
|
||||||
const res = await request
|
|
||||||
.get(`/api/hosting/apps`)
|
|
||||||
.set(config.defaultHeaders())
|
|
||||||
.expect("Content-Type", /json/)
|
|
||||||
.expect(200)
|
|
||||||
expect(res.body.app1).toEqual({url: "/app1"})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
|
@ -8,11 +8,6 @@ const StaticDatabases = {
|
||||||
name: "builder-db",
|
name: "builder-db",
|
||||||
baseDoc: "builder-doc",
|
baseDoc: "builder-doc",
|
||||||
},
|
},
|
||||||
// TODO: needs removed
|
|
||||||
BUILDER_HOSTING: {
|
|
||||||
name: "builder-config-db",
|
|
||||||
baseDoc: "hosting-doc",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DocumentTypes = {
|
const DocumentTypes = {
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
const CouchDB = require("../../db")
|
|
||||||
const { StaticDatabases } = require("../../db/utils")
|
|
||||||
const { getDeployedApps } = require("../../utilities/workerRequests")
|
|
||||||
|
|
||||||
const PROD_HOSTING_URL = "app.budi.live"
|
|
||||||
|
|
||||||
function getProtocol(hostingInfo) {
|
|
||||||
return hostingInfo.useHttps ? "https://" : "http://"
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getURLWithPath(pathIfSelfHosted) {
|
|
||||||
const hostingInfo = await exports.getHostingInfo()
|
|
||||||
const protocol = getProtocol(hostingInfo)
|
|
||||||
const path =
|
|
||||||
hostingInfo.type === exports.HostingTypes.SELF ? pathIfSelfHosted : ""
|
|
||||||
return `${protocol}${hostingInfo.hostingUrl}${path}`
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.HostingTypes = {
|
|
||||||
CLOUD: "cloud",
|
|
||||||
SELF: "self",
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getHostingInfo = async () => {
|
|
||||||
const db = new CouchDB(StaticDatabases.BUILDER_HOSTING.name)
|
|
||||||
let doc
|
|
||||||
try {
|
|
||||||
doc = await db.get(StaticDatabases.BUILDER_HOSTING.baseDoc)
|
|
||||||
} catch (err) {
|
|
||||||
// don't write this doc, want to be able to update these default props
|
|
||||||
// for our servers with a new release without needing to worry about state of
|
|
||||||
// PouchDB in peoples installations
|
|
||||||
doc = {
|
|
||||||
_id: StaticDatabases.BUILDER_HOSTING.baseDoc,
|
|
||||||
type: exports.HostingTypes.CLOUD,
|
|
||||||
hostingUrl: PROD_HOSTING_URL,
|
|
||||||
selfHostKey: "",
|
|
||||||
templatesUrl: "prod-budi-templates.s3-eu-west-1.amazonaws.com",
|
|
||||||
useHttps: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getAppUrl = async appId => {
|
|
||||||
const hostingInfo = await exports.getHostingInfo()
|
|
||||||
const protocol = getProtocol(hostingInfo)
|
|
||||||
let url
|
|
||||||
if (hostingInfo.type === exports.HostingTypes.CLOUD) {
|
|
||||||
url = `${protocol}${appId}.${hostingInfo.hostingUrl}`
|
|
||||||
} else {
|
|
||||||
url = `${protocol}${hostingInfo.hostingUrl}/app`
|
|
||||||
}
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getWorkerUrl = async () => {
|
|
||||||
return getURLWithPath("/worker")
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getMinioUrl = async () => {
|
|
||||||
return getURLWithPath("/")
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getCouchUrl = async () => {
|
|
||||||
return getURLWithPath("/db")
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getSelfHostKey = async () => {
|
|
||||||
const hostingInfo = await exports.getHostingInfo()
|
|
||||||
return hostingInfo.selfHostKey
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getTemplatesUrl = async (appId, type, name) => {
|
|
||||||
const hostingInfo = await exports.getHostingInfo()
|
|
||||||
const protocol = getProtocol(hostingInfo)
|
|
||||||
let path
|
|
||||||
if (type && name) {
|
|
||||||
path = `templates/type/${name}.tar.gz`
|
|
||||||
} else {
|
|
||||||
path = "manifest.json"
|
|
||||||
}
|
|
||||||
return `${protocol}${hostingInfo.templatesUrl}/${path}`
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getDeployedApps = getDeployedApps
|
|
|
@ -37,9 +37,6 @@ function request(ctx, request) {
|
||||||
exports.request = request
|
exports.request = request
|
||||||
|
|
||||||
exports.getDeployedApps = async ctx => {
|
exports.getDeployedApps = async ctx => {
|
||||||
if (!env.SELF_HOSTED) {
|
|
||||||
throw "Can only check apps for self hosted environments"
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
checkSlashesInUrl(env.WORKER_URL + `/api/apps`),
|
checkSlashesInUrl(env.WORKER_URL + `/api/apps`),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "0.8.16",
|
"version": "0.8.16",
|
||||||
"description": "Budibase Deployment Server",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const { Configs } = require("@budibase/auth").constants
|
||||||
|
|
||||||
exports.LOGO_URL =
|
exports.LOGO_URL =
|
||||||
"https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg"
|
"https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg"
|
||||||
|
|
||||||
|
@ -10,12 +12,7 @@ exports.Groups = {
|
||||||
ALL_USERS: "all_users",
|
ALL_USERS: "all_users",
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.Configs = {
|
exports.Configs = Configs
|
||||||
SETTINGS: "settings",
|
|
||||||
ACCOUNT: "account",
|
|
||||||
SMTP: "smtp",
|
|
||||||
GOOGLE: "google",
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.ConfigUploads = {
|
exports.ConfigUploads = {
|
||||||
LOGO: "logo",
|
LOGO: "logo",
|
||||||
|
|
Loading…
Reference in New Issue