1
0
Fork 0
mirror of synced 2024-06-27 18:40:42 +12:00

Getting rid of the CLOUD environment variable, this makes no sense anymore, now there is isDev() and isProd() which will work out the current state of the cluster.

This commit is contained in:
mike12345567 2021-03-24 18:21:23 +00:00
parent e9ed014bac
commit 73cf53d149
39 changed files with 150 additions and 163 deletions

View file

@ -11,7 +11,6 @@ services:
- "${APP_PORT}:4002" - "${APP_PORT}:4002"
environment: environment:
SELF_HOSTED: 1 SELF_HOSTED: 1
CLOUD: 1
COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984 COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984
WORKER_URL: http://worker-service:4003 WORKER_URL: http://worker-service:4003
MINIO_URL: http://minio-service:9000 MINIO_URL: http://minio-service:9000

View file

@ -2,7 +2,6 @@ FROM node:12-alpine
WORKDIR /app WORKDIR /app
ENV CLOUD=1
ENV PORT=4001 ENV PORT=4001
ENV COUCH_DB_URL=https://couchdb.budi.live:5984 ENV COUCH_DB_URL=https://couchdb.budi.live:5984
ENV BUDIBASE_ENVIRONMENT=PRODUCTION ENV BUDIBASE_ENVIRONMENT=PRODUCTION

View file

@ -43,7 +43,6 @@ 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,
CLOUD: 1,
} }
let envFile = "" let envFile = ""
Object.keys(envFileJson).forEach(key => { Object.keys(envFileJson).forEach(key => {

View file

@ -30,8 +30,6 @@ const { getAllApps } = require("../../utilities")
const { USERS_TABLE_SCHEMA } = require("../../constants") const { USERS_TABLE_SCHEMA } = require("../../constants")
const { const {
getDeployedApps, getDeployedApps,
getHostingInfo,
HostingTypes,
} = require("../../utilities/builder/hosting") } = require("../../utilities/builder/hosting")
const URL_REGEX_SLASH = /\/|\\/g const URL_REGEX_SLASH = /\/|\\/g
@ -71,8 +69,7 @@ async function getAppUrlIfNotInUse(ctx) {
url = encodeURI(`${ctx.request.body.name}`) url = encodeURI(`${ctx.request.body.name}`)
} }
url = `/${url.replace(URL_REGEX_SLASH, "")}`.toLowerCase() url = `/${url.replace(URL_REGEX_SLASH, "")}`.toLowerCase()
const hostingInfo = await getHostingInfo() if (!env.SELF_HOSTED) {
if (hostingInfo.type === HostingTypes.CLOUD) {
return url return url
} }
const deployedApps = await getDeployedApps() const deployedApps = await getDeployedApps()

View file

@ -45,9 +45,9 @@ exports.authenticate = async ctx => {
roleId: dbUser.roleId, roleId: dbUser.roleId,
version: app.version, version: app.version,
} }
// if in cloud add the user api key, unless self hosted // if in prod add the user api key, unless self hosted
/* istanbul ignore next */ /* istanbul ignore next */
if (env.CLOUD && !env.SELF_HOSTED) { if (env.isProd() && !env.SELF_HOSTED) {
const { apiKey } = await getAPIKey(ctx.user.appId) const { apiKey } = await getAPIKey(ctx.user.appId)
payload.apiKey = apiKey payload.apiKey = apiKey
} }

View file

@ -2,6 +2,7 @@ const CouchDB = require("../../db")
const { join } = require("../../utilities/centralPath") const { join } = require("../../utilities/centralPath")
const { budibaseTempDir } = require("../../utilities/budibaseDir") const { budibaseTempDir } = require("../../utilities/budibaseDir")
const fileSystem = require("../../utilities/fileSystem") const fileSystem = require("../../utilities/fileSystem")
const env = require("../../environment")
exports.fetchAppComponentDefinitions = async function(ctx) { exports.fetchAppComponentDefinitions = async function(ctx) {
const appId = ctx.params.appId || ctx.appId const appId = ctx.params.appId || ctx.appId
@ -11,13 +12,8 @@ exports.fetchAppComponentDefinitions = async function(ctx) {
let componentManifests = await Promise.all( let componentManifests = await Promise.all(
app.componentLibraries.map(async library => { app.componentLibraries.map(async library => {
let manifest let manifest
if (ctx.isDev) { if (env.isDev()) {
manifest = require(join( manifest = require(join(budibaseTempDir(), library, "manifest.json"))
budibaseTempDir(),
library,
ctx.isDev ? "" : "package",
"manifest.json"
))
} else { } else {
manifest = await fileSystem.getComponentLibraryManifest(appId, library) manifest = await fileSystem.getComponentLibraryManifest(appId, library)
} }

View file

@ -93,7 +93,7 @@ exports.find = async function(ctx) {
const db = new CouchDB(ctx.user.appId) const db = new CouchDB(ctx.user.appId)
const query = enrichQueries(await db.get(ctx.params.queryId)) const query = enrichQueries(await db.get(ctx.params.queryId))
// remove properties that could be dangerous in real app // remove properties that could be dangerous in real app
if (env.CLOUD) { if (env.isProd()) {
delete query.fields delete query.fields
delete query.parameters delete query.parameters
delete query.schema delete query.schema

View file

@ -87,7 +87,7 @@ exports.serveApp = async function(ctx) {
const { head, html, css } = App.render({ const { head, html, css } = App.render({
title: appInfo.name, title: appInfo.name,
production: env.CLOUD, production: env.isProd(),
appId, appId,
objectStoreUrl: objectStoreUrl(), objectStoreUrl: objectStoreUrl(),
}) })
@ -106,7 +106,7 @@ exports.serveAttachment = async function(ctx) {
const attachmentsPath = resolve(budibaseAppsDir(), appId, "attachments") const attachmentsPath = resolve(budibaseAppsDir(), appId, "attachments")
// Serve from object store // Serve from object store
if (env.CLOUD) { if (env.isProd()) {
const S3_URL = join(objectStoreUrl(), appId, "attachments", ctx.file) const S3_URL = join(objectStoreUrl(), appId, "attachments", ctx.file)
const response = await fetch(S3_URL) const response = await fetch(S3_URL)
const body = await response.text() const body = await response.text()
@ -137,15 +137,13 @@ exports.serveComponentLibrary = async function(ctx) {
"dist" "dist"
) )
if (ctx.isDev) { if (env.isDev()) {
componentLibraryPath = join( componentLibraryPath = join(
budibaseTempDir(), budibaseTempDir(),
decodeURI(ctx.query.library), decodeURI(ctx.query.library),
"dist" "dist"
) )
} } else {
if (env.CLOUD) {
let componentLib = "componentlibrary" let componentLib = "componentlibrary"
if (ctx.user.version) { if (ctx.user.version) {
componentLib += `-${ctx.user.version}` componentLib += `-${ctx.user.version}`

View file

@ -3,7 +3,6 @@ const authenticated = require("../middleware/authenticated")
const compress = require("koa-compress") const compress = require("koa-compress")
const zlib = require("zlib") const zlib = require("zlib")
const { budibaseAppsDir } = require("../utilities/budibaseDir") const { budibaseAppsDir } = require("../utilities/budibaseDir")
const { isDev } = require("../utilities")
const { mainRoutes, authRoutes, staticRoutes } = require("./routes") const { mainRoutes, authRoutes, staticRoutes } = require("./routes")
const pkg = require("../../package.json") const pkg = require("../../package.json")
@ -29,7 +28,6 @@ router
jwtSecret: env.JWT_SECRET, jwtSecret: env.JWT_SECRET,
useAppRootPath: true, useAppRootPath: true,
} }
ctx.isDev = isDev()
await next() await next()
}) })
.use("/health", ctx => (ctx.status = 200)) .use("/health", ctx => (ctx.status = 200))

View file

@ -13,7 +13,7 @@ router.param("file", async (file, ctx, next) => {
ctx.file = file && file.includes(".") ? file : "index.html" ctx.file = file && file.includes(".") ? file : "index.html"
// Serving the client library from your local dir in dev // Serving the client library from your local dir in dev
if (ctx.isDev && ctx.file.startsWith("budibase-client")) { if (env.isDev() && ctx.file.startsWith("budibase-client")) {
ctx.devPath = budibaseTempDir() ctx.devPath = budibaseTempDir()
} }

View file

@ -13,7 +13,7 @@ describe("/api/keys", () => {
describe("fetch", () => { describe("fetch", () => {
it("should allow fetching", async () => { it("should allow fetching", async () => {
await setup.switchToCloudForFunction(async () => { await setup.switchToSelfHosted(async () => {
const res = await request const res = await request
.get(`/api/keys`) .get(`/api/keys`)
.set(config.defaultHeaders()) .set(config.defaultHeaders())
@ -34,7 +34,7 @@ describe("/api/keys", () => {
describe("update", () => { describe("update", () => {
it("should allow updating a value", async () => { it("should allow updating a value", async () => {
await setup.switchToCloudForFunction(async () => { await setup.switchToSelfHosted(async () => {
const res = await request const res = await request
.put(`/api/keys/TEST`) .put(`/api/keys/TEST`)
.send({ .send({

View file

@ -107,17 +107,16 @@ describe("/hosting", () => {
}) })
describe("getDeployedApps", () => { describe("getDeployedApps", () => {
it("should get apps when in builder", async () => { it("should fail when not self hosted", async () => {
const res = await request await request
.get(`/api/hosting/apps`) .get(`/api/hosting/apps`)
.set(config.defaultHeaders()) .set(config.defaultHeaders())
.expect("Content-Type", /json/) .expect("Content-Type", /json/)
.expect(200) .expect(400)
expect(res.body.app1).toEqual({url: "/app1"})
}) })
it("should get apps when in cloud", async () => { it("should get apps when in cloud", async () => {
await setup.switchToCloudForFunction(async () => { await setup.switchToSelfHosted(async () => {
const res = await request const res = await request
.get(`/api/hosting/apps`) .get(`/api/hosting/apps`)
.set(config.defaultHeaders()) .set(config.defaultHeaders())

View file

@ -89,7 +89,7 @@ describe("/queries", () => {
}) })
it("should find a query in cloud", async () => { it("should find a query in cloud", async () => {
await setup.switchToCloudForFunction(async () => { await setup.switchToSelfHosted(async () => {
const query = await config.createQuery() const query = await config.createQuery()
const res = await request const res = await request
.get(`/api/queries/${query._id}`) .get(`/api/queries/${query._id}`)

View file

@ -410,7 +410,7 @@ describe("/rows", () => {
tableId: table._id, tableId: table._id,
}) })
// the environment needs configured for this // the environment needs configured for this
await setup.switchToCloudForFunction(async () => { await setup.switchToSelfHosted(async () => {
const enriched = await outputProcessing(config.getAppId(), table, [row]) const enriched = await outputProcessing(config.getAppId(), table, [row])
expect(enriched[0].attachment[0].url).toBe(`/app-assets/assets/${config.getAppId()}/test/thing`) expect(enriched[0].attachment[0].url).toBe(`/app-assets/assets/${config.getAppId()}/test/thing`)
}) })

View file

@ -35,18 +35,18 @@ exports.getConfig = () => {
return config return config
} }
exports.switchToCloudForFunction = async func => { exports.switchToSelfHosted = async func => {
// self hosted stops any attempts to Dynamo // self hosted stops any attempts to Dynamo
env.CLOUD = true env._set("NODE_ENV", "production")
env.SELF_HOSTED = true env._set("SELF_HOSTED", true)
let error let error
try { try {
await func() await func()
} catch (err) { } catch (err) {
error = err error = err
} }
env.CLOUD = false env._set("NODE_ENV", "jest")
env.SELF_HOSTED = false env._set("SELF_HOSTED", false)
// don't throw error until after reset // don't throw error until after reset
if (error) { if (error) {
throw error throw error

View file

@ -41,7 +41,7 @@ module.exports.getAction = async function(actionName) {
return BUILTIN_ACTIONS[actionName] return BUILTIN_ACTIONS[actionName]
} }
// worker pools means that a worker may not have manifest // worker pools means that a worker may not have manifest
if (env.CLOUD && MANIFEST == null) { if (env.isProd() && MANIFEST == null) {
MANIFEST = await module.exports.init() MANIFEST = await module.exports.init()
} }
// env setup to get async packages // env setup to get async packages

View file

@ -34,10 +34,10 @@ module.exports.init = async function() {
await actions.init() await actions.init()
triggers.automationQueue.process(async job => { triggers.automationQueue.process(async job => {
try { try {
if (env.CLOUD && job.data.automation && !env.SELF_HOSTED) { if (env.USE_QUOTAS) {
job.data.automation.apiKey = await updateQuota(job.data.automation) job.data.automation.apiKey = await updateQuota(job.data.automation)
} }
if (env.BUDIBASE_ENVIRONMENT === "PRODUCTION") { if (env.isProd()) {
await runWorker(job) await runWorker(job)
} else { } else {
await singleThread(job) await singleThread(job)

View file

@ -85,7 +85,7 @@ module.exports.run = async function({ inputs, appId, apiKey, emitter }) {
inputs.row.tableId, inputs.row.tableId,
inputs.row inputs.row
) )
if (env.CLOUD) { if (env.isProd()) {
await usage.update(apiKey, usage.Properties.ROW, 1) await usage.update(apiKey, usage.Properties.ROW, 1)
} }
await rowController.save(ctx) await rowController.save(ctx)

View file

@ -72,7 +72,7 @@ module.exports.run = async function({ inputs, appId, apiKey, emitter }) {
} }
try { try {
if (env.CLOUD) { if (env.isProd()) {
await usage.update(apiKey, usage.Properties.USER, 1) await usage.update(apiKey, usage.Properties.USER, 1)
} }
await userController.create(ctx) await userController.create(ctx)

View file

@ -70,7 +70,7 @@ module.exports.run = async function({ inputs, appId, apiKey, emitter }) {
} }
try { try {
if (env.CLOUD) { if (env.isProd()) {
await usage.update(apiKey, usage.Properties.ROW, -1) await usage.update(apiKey, usage.Properties.ROW, -1)
} }
await rowController.destroy(ctx) await rowController.destroy(ctx)

View file

@ -47,27 +47,23 @@ describe("Run through some parts of the automations system", () => {
expect(thread).toHaveBeenCalled() expect(thread).toHaveBeenCalled()
}) })
it("should be able to init in cloud", async () => { it("should be able to init in prod", async () => {
env.CLOUD = true await setup.runInProd(async () => {
env.BUDIBASE_ENVIRONMENT = "PRODUCTION" await triggers.externalTrigger(basicAutomation(), { a: 1 })
await triggers.externalTrigger(basicAutomation(), { a: 1 }) await wait(100)
await wait(100) // haven't added a mock implementation so getAPIKey of usageQuota just returns undefined
// haven't added a mock implementation so getAPIKey of usageQuota just returns undefined expect(usageQuota.update).toHaveBeenCalledWith("test", "automationRuns", 1)
expect(usageQuota.update).toHaveBeenCalledWith("test", "automationRuns", 1) expect(workerJob).toBeDefined()
expect(workerJob).toBeDefined() })
env.BUDIBASE_ENVIRONMENT = "JEST"
env.CLOUD = false
}) })
it("try error scenario", async () => { it("try error scenario", async () => {
env.CLOUD = true await setup.runInProd(async () => {
env.BUDIBASE_ENVIRONMENT = "PRODUCTION" // the second call will throw an error
// the second call will throw an error await triggers.externalTrigger(basicAutomation(), { a: 1 })
await triggers.externalTrigger(basicAutomation(), { a: 1 }) await wait(100)
await wait(100) expect(console.error).toHaveBeenCalled()
expect(console.error).toHaveBeenCalled() })
env.BUDIBASE_ENVIRONMENT = "JEST"
env.CLOUD = false
}) })
it("should be able to check triggering row filling", async () => { it("should be able to check triggering row filling", async () => {

View file

@ -42,12 +42,12 @@ describe("test the create row action", () => {
}) })
it("check usage quota attempts", async () => { it("check usage quota attempts", async () => {
env.CLOUD = true await setup.runInProd(async () => {
await setup.runStep(setup.actions.CREATE_ROW.stepId, { await setup.runStep(setup.actions.CREATE_ROW.stepId, {
row row
})
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "rows", 1)
}) })
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "rows", 1)
env.CLOUD = false
}) })
it("should check invalid inputs return an error", async () => { it("should check invalid inputs return an error", async () => {

View file

@ -35,9 +35,9 @@ describe("test the create user action", () => {
}) })
it("check usage quota attempts", async () => { it("check usage quota attempts", async () => {
env.CLOUD = true await setup.runInProd(async () => {
await setup.runStep(setup.actions.CREATE_USER.stepId, user) await setup.runStep(setup.actions.CREATE_USER.stepId, user)
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "users", 1) expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "users", 1)
env.CLOUD = false })
}) })
}) })

View file

@ -36,10 +36,10 @@ describe("test the delete row action", () => {
}) })
it("check usage quota attempts", async () => { it("check usage quota attempts", async () => {
env.CLOUD = true await setup.runInProd(async () => {
await setup.runStep(setup.actions.DELETE_ROW.stepId, inputs) await setup.runStep(setup.actions.DELETE_ROW.stepId, inputs)
expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "rows", -1) expect(usageQuota.update).toHaveBeenCalledWith(setup.apiKey, "rows", -1)
env.CLOUD = false })
}) })
it("should check invalid inputs return an error", async () => { it("should check invalid inputs return an error", async () => {

View file

@ -2,6 +2,7 @@ const TestConfig = require("../../../tests/utilities/TestConfiguration")
const actions = require("../../actions") const actions = require("../../actions")
const logic = require("../../logic") const logic = require("../../logic")
const emitter = require("../../../events/index") const emitter = require("../../../events/index")
const env = require("../../../environment")
let config let config
@ -16,6 +17,22 @@ exports.afterAll = () => {
config.end() config.end()
} }
exports.runInProd = async fn => {
env._set("NODE_ENV", "production")
env._set("USE_QUOTAS", 1)
let error
try {
await fn()
} catch (err) {
error = err
}
env._set("NODE_ENV", "jest")
env._set("USE_QUOTAS", null)
if (error) {
throw error
}
}
exports.runStep = async function runStep(stepId, inputs) { exports.runStep = async function runStep(stepId, inputs) {
let step let step
if ( if (

View file

@ -5,7 +5,6 @@ const find = require("pouchdb-find")
const env = require("../environment") const env = require("../environment")
const COUCH_DB_URL = env.COUCH_DB_URL || "http://localhost:10000/db/" const COUCH_DB_URL = env.COUCH_DB_URL || "http://localhost:10000/db/"
const isInMemory = env.NODE_ENV === "jest"
PouchDB.plugin(replicationStream.plugin) PouchDB.plugin(replicationStream.plugin)
PouchDB.plugin(find) PouchDB.plugin(find)
@ -13,10 +12,10 @@ PouchDB.adapter("writableStream", replicationStream.adapters.writableStream)
let POUCH_DB_DEFAULTS = { let POUCH_DB_DEFAULTS = {
prefix: COUCH_DB_URL, prefix: COUCH_DB_URL,
skip_setup: !!env.CLOUD, skip_setup: env.isProd(),
} }
if (isInMemory) { if (env.isTest()) {
PouchDB.plugin(require("pouchdb-adapter-memory")) PouchDB.plugin(require("pouchdb-adapter-memory"))
POUCH_DB_DEFAULTS = { POUCH_DB_DEFAULTS = {
prefix: undefined, prefix: undefined,

View file

@ -1,4 +1,4 @@
let _ = require("lodash") let { merge } = require("lodash")
let env = require("../environment") let env = require("../environment")
const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1" const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1"
@ -38,7 +38,7 @@ class Table {
params.Key[this._sort] = sort params.Key[this._sort] = sort
} }
if (otherProps) { if (otherProps) {
params = _.merge(params, otherProps) params = merge(params, otherProps)
} }
let response = await docClient.get(params).promise() let response = await docClient.get(params).promise()
return response.Item return response.Item
@ -77,7 +77,7 @@ class Table {
params.ConditionExpression += "attribute_exists(#PRIMARY)" params.ConditionExpression += "attribute_exists(#PRIMARY)"
} }
if (otherProps) { if (otherProps) {
params = _.merge(params, otherProps) params = merge(params, otherProps)
} }
return docClient.update(params).promise() return docClient.update(params).promise()
} }
@ -94,7 +94,7 @@ class Table {
Item: item, Item: item,
} }
if (otherProps) { if (otherProps) {
params = _.merge(params, otherProps) params = merge(params, otherProps)
} }
return docClient.put(params).promise() return docClient.put(params).promise()
} }
@ -119,7 +119,7 @@ exports.init = endpoint => {
exports.apiKeyTable = new Table(TableInfo.API_KEYS) exports.apiKeyTable = new Table(TableInfo.API_KEYS)
exports.userTable = new Table(TableInfo.USERS) exports.userTable = new Table(TableInfo.USERS)
if (env.CLOUD) { if (env.isProd()) {
exports.init(`https://dynamodb.${AWS_REGION}.amazonaws.com`) exports.init(`https://dynamodb.${AWS_REGION}.amazonaws.com`)
} else { } else {
env._set("AWS_ACCESS_KEY_ID", "KEY_ID") env._set("AWS_ACCESS_KEY_ID", "KEY_ID")

View file

@ -1,15 +1,20 @@
function isTest() {
return (
process.env.NODE_ENV === "jest" ||
process.env.NODE_ENV === "cypress" ||
process.env.JEST_WORKER_ID != null
)
}
function isDev() { function isDev() {
return ( return (
!process.env.CLOUD &&
process.env.NODE_ENV !== "production" && process.env.NODE_ENV !== "production" &&
process.env.NODE_ENV !== "jest" && process.env.BUDIBASE_ENVIRONMENT !== "production"
process.env.NODE_ENV !== "cypress" &&
process.env.JEST_WORKER_ID == null
) )
} }
let LOADED = false let LOADED = false
if (!LOADED && isDev()) { if (!LOADED && isDev() && !isTest()) {
require("dotenv").config() require("dotenv").config()
LOADED = true LOADED = true
} }
@ -21,12 +26,12 @@ module.exports = {
COUCH_DB_URL: process.env.COUCH_DB_URL, COUCH_DB_URL: process.env.COUCH_DB_URL,
MINIO_URL: process.env.MINIO_URL, MINIO_URL: process.env.MINIO_URL,
WORKER_URL: process.env.WORKER_URL, WORKER_URL: process.env.WORKER_URL,
CLOUD: process.env.CLOUD,
SELF_HOSTED: process.env.SELF_HOSTED, SELF_HOSTED: process.env.SELF_HOSTED,
AWS_REGION: process.env.AWS_REGION, AWS_REGION: process.env.AWS_REGION,
ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS, ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS,
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
USE_QUOTAS: process.env.USE_QUOTAS,
// environment // environment
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,
@ -51,5 +56,9 @@ module.exports = {
process.env[key] = value process.env[key] = value
module.exports[key] = value module.exports[key] = value
}, },
isTest,
isDev, isDev,
isProd: () => {
return !isDev()
},
} }

View file

@ -18,7 +18,7 @@ function hasResource(ctx) {
} }
module.exports = (permType, permLevel = null) => async (ctx, next) => { module.exports = (permType, permLevel = null) => async (ctx, next) => {
if (env.CLOUD && ctx.headers["x-api-key"] && ctx.headers["x-instanceid"]) { if (env.isProd() && ctx.headers["x-api-key"] && ctx.headers["x-instanceid"]) {
// api key header passed by external webhook // api key header passed by external webhook
if (await isAPIKeyValid(ctx.headers["x-api-key"])) { if (await isAPIKeyValid(ctx.headers["x-api-key"])) {
ctx.auth = { ctx.auth = {

View file

@ -1,14 +1,8 @@
const env = require("../environment") const env = require("../environment")
const hosting = require("../utilities/builder/hosting")
// if added as a middleware will stop requests unless builder is in self host mode // if added as a middleware will stop requests unless builder is in self host mode
// or cloud is in self host // or cloud is in self host
module.exports = async (ctx, next) => { module.exports = async (ctx, next) => {
if (env.CLOUD && env.SELF_HOSTED) { if (env.SELF_HOSTED) {
await next()
return
}
const hostingInfo = await hosting.getHostingInfo()
if (hostingInfo.type === hosting.HostingTypes.SELF) {
await next() await next()
return return
} }

View file

@ -3,8 +3,15 @@ const env = require("../../environment")
const apiKey = require("../../utilities/security/apikey") const apiKey = require("../../utilities/security/apikey")
const { AuthTypes } = require("../../constants") const { AuthTypes } = require("../../constants")
const { PermissionTypes, PermissionLevels } = require("../../utilities/security/permissions") const { PermissionTypes, PermissionLevels } = require("../../utilities/security/permissions")
const { Test } = require("supertest") jest.mock("../../environment", () => ({
jest.mock("../../environment") prod: false,
isTest: () => true,
isProd: () => this.prod,
_set: (key, value) => {
this.prod = value === "production"
}
})
)
jest.mock("../../utilities/security/apikey") jest.mock("../../utilities/security/apikey")
class TestConfiguration { class TestConfiguration {
@ -47,8 +54,8 @@ class TestConfiguration {
this.ctx.request.url = url this.ctx.request.url = url
} }
setCloudEnv(isCloud) { setEnvironment(isProd) {
env.CLOUD = isCloud env._set("NODE_ENV", isProd ? "production" : "jest")
} }
setRequestHeaders(headers) { setRequestHeaders(headers) {
@ -79,7 +86,7 @@ describe("Authorization middleware", () => {
beforeEach(() => { beforeEach(() => {
config = new TestConfiguration() config = new TestConfiguration()
config.setCloudEnv(true) config.setEnvironment(true)
config.setRequestHeaders({ config.setRequestHeaders({
"x-api-key": "abc123", "x-api-key": "abc123",
"x-instanceid": "instance123", "x-instanceid": "instance123",
@ -115,7 +122,7 @@ describe("Authorization middleware", () => {
beforeEach(() => { beforeEach(() => {
config = new TestConfiguration() config = new TestConfiguration()
config.setCloudEnv(true) config.setEnvironment(true)
config.setAuthenticated(true) config.setAuthenticated(true)
}) })
@ -138,7 +145,7 @@ describe("Authorization middleware", () => {
}) })
it("throws if the user has only builder permissions", async () => { it("throws if the user has only builder permissions", async () => {
config.setCloudEnv(false) config.setEnvironment(false)
config.setMiddlewareRequiredPermission(PermissionTypes.BUILDER) config.setMiddlewareRequiredPermission(PermissionTypes.BUILDER)
config.setUser({ config.setUser({
role: { role: {

View file

@ -1,6 +1,5 @@
const selfHostMiddleware = require("../selfhost"); const selfHostMiddleware = require("../selfhost")
const env = require("../../environment") const env = require("../../environment")
const hosting = require("../../utilities/builder/hosting");
jest.mock("../../environment") jest.mock("../../environment")
jest.mock("../../utilities/builder/hosting") jest.mock("../../utilities/builder/hosting")
@ -20,16 +19,6 @@ class TestConfiguration {
return this.middleware(this.ctx, this.next) return this.middleware(this.ctx, this.next)
} }
setCloudHosted() {
env.CLOUD = 1
env.SELF_HOSTED = 0
}
setSelfHosted() {
env.CLOUD = 0
env.SELF_HOSTED = 1
}
afterEach() { afterEach() {
jest.clearAllMocks() jest.clearAllMocks()
} }
@ -46,30 +35,10 @@ describe("Self host middleware", () => {
config.afterEach() config.afterEach()
}) })
it("calls next() when CLOUD and SELF_HOSTED env vars are set", async () => { it("calls next() when SELF_HOSTED env var is set", async () => {
env.CLOUD = 1
env.SELF_HOSTED = 1 env.SELF_HOSTED = 1
await config.executeMiddleware() await config.executeMiddleware()
expect(config.next).toHaveBeenCalled() expect(config.next).toHaveBeenCalled()
}) })
it("throws when hostingInfo type is cloud", async () => {
config.setSelfHosted()
hosting.getHostingInfo.mockImplementationOnce(() => ({ type: hosting.HostingTypes.CLOUD }))
await config.executeMiddleware()
expect(config.throw).toHaveBeenCalledWith(400, "Endpoint unavailable in cloud hosting.")
expect(config.next).not.toHaveBeenCalled()
})
it("calls the self hosting middleware to pass through to next() when the hostingInfo type is self", async () => {
config.setSelfHosted()
hosting.getHostingInfo.mockImplementationOnce(() => ({ type: hosting.HostingTypes.SELF }))
await config.executeMiddleware()
expect(config.next).toHaveBeenCalled()
})
}) })

View file

@ -5,7 +5,12 @@ const env = require("../../environment")
jest.mock("../../db") jest.mock("../../db")
jest.mock("../../utilities/usageQuota") jest.mock("../../utilities/usageQuota")
jest.mock("../../environment") jest.mock("../../environment", () => ({
isTest: () => true,
isProd: () => false,
isDev: () => true,
_set: () => {},
}))
class TestConfiguration { class TestConfiguration {
constructor() { constructor() {
@ -32,12 +37,14 @@ class TestConfiguration {
return this.middleware(this.ctx, this.next) return this.middleware(this.ctx, this.next)
} }
cloudHosted(bool) { setProd(bool) {
if (bool) { if (bool) {
env.CLOUD = 1 env.isDev = () => false
env.isProd = () => true
this.ctx.auth = { apiKey: "test" } this.ctx.auth = { apiKey: "test" }
} else { } else {
env.CLOUD = 0 env.isDev = () => true
env.isProd = () => false
} }
} }
@ -102,7 +109,7 @@ describe("usageQuota middleware", () => {
it("calculates and persists the correct usage quota for the relevant action", async () => { it("calculates and persists the correct usage quota for the relevant action", async () => {
config.setUrl("/rows") config.setUrl("/rows")
config.cloudHosted(true) config.setProd(true)
await config.executeMiddleware() await config.executeMiddleware()
@ -112,7 +119,7 @@ describe("usageQuota middleware", () => {
it("calculates the correct file size from a file upload call and adds it to quota", async () => { it("calculates the correct file size from a file upload call and adds it to quota", async () => {
config.setUrl("/upload") config.setUrl("/upload")
config.cloudHosted(true) config.setProd(true)
config.setFiles([ config.setFiles([
{ {
size: 100 size: 100

View file

@ -44,8 +44,8 @@ module.exports = async (ctx, next) => {
} }
} }
// if running in builder or a self hosted cloud usage quotas should not be executed // if in development or a self hosted cloud usage quotas should not be executed
if (!env.CLOUD || env.SELF_HOSTED) { if (env.isDev() || env.SELF_HOSTED) {
return next() return next()
} }
// update usage for uploads to be the total size // update usage for uploads to be the total size

View file

@ -71,7 +71,8 @@ class TestConfiguration {
roleId: BUILTIN_ROLE_IDS.BUILDER, roleId: BUILTIN_ROLE_IDS.BUILDER,
} }
const builderToken = jwt.sign(builderUser, env.JWT_SECRET) const builderToken = jwt.sign(builderUser, env.JWT_SECRET)
const type = env.CLOUD ? "cloud" : "local" // can be "production" for test case
const type = env.isProd() ? "cloud" : "local"
const headers = { const headers = {
Accept: "application/json", Accept: "application/json",
Cookie: [`budibase:builder:${type}=${builderToken}`], Cookie: [`budibase:builder:${type}=${builderToken}`],

View file

@ -85,15 +85,11 @@ exports.getTemplatesUrl = async (appId, type, name) => {
} }
exports.getDeployedApps = async () => { exports.getDeployedApps = async () => {
const hostingInfo = await exports.getHostingInfo() if (!env.SELF_HOSTED) {
if (
(!env.CLOUD && hostingInfo.type === exports.HostingTypes.CLOUD) ||
(env.CLOUD && !env.SELF_HOSTED)
) {
throw "Can only check apps for self hosted environments" throw "Can only check apps for self hosted environments"
} }
const workerUrl = !env.CLOUD ? await exports.getWorkerUrl() : env.WORKER_URL const workerUrl = env.WORKER_URL
const hostingKey = !env.CLOUD ? hostingInfo.selfHostKey : env.HOSTING_KEY const hostingKey = env.HOSTING_KEY
try { try {
const response = await fetch(`${workerUrl}/api/apps`, { const response = await fetch(`${workerUrl}/api/apps`, {
method: "GET", method: "GET",

View file

@ -20,10 +20,18 @@ exports.isDev = env.isDev
* @returns {string|undefined} If an appId was found it will be returned. * @returns {string|undefined} If an appId was found it will be returned.
*/ */
exports.getAppId = ctx => { exports.getAppId = ctx => {
let appId = confirmAppId(ctx.headers["x-budibase-app-id"]) const options = [ctx.headers["x-budibase-app-id"], ctx.params.appId]
if (!appId) { if (ctx.subdomains) {
appId = confirmAppId(env.CLOUD ? ctx.subdomains[1] : ctx.params.appId) options.push(ctx.subdomains[1])
} }
let appId
for (let option of options) {
appId = confirmAppId(option)
if (appId) {
break
}
}
// look in body if can't find it in subdomain // look in body if can't find it in subdomain
if (!appId && ctx.request.body && ctx.request.body.appId) { if (!appId && ctx.request.body && ctx.request.body.appId) {
appId = confirmAppId(ctx.request.body.appId) appId = confirmAppId(ctx.request.body.appId)
@ -43,7 +51,7 @@ exports.getAppId = ctx => {
* @returns {string} The name of the token trying to find * @returns {string} The name of the token trying to find
*/ */
exports.getCookieName = (name = "builder") => { exports.getCookieName = (name = "builder") => {
let environment = env.CLOUD ? "cloud" : "local" let environment = env.isProd() ? "cloud" : "local"
return `budibase:${name}:${environment}` return `budibase:${name}:${environment}`
} }

View file

@ -180,7 +180,7 @@ exports.outputProcessing = async (appId, table, rows) => {
rows rows
) )
// update the attachments URL depending on hosting // update the attachments URL depending on hosting
if (env.CLOUD && env.SELF_HOSTED) { if (env.isProd() && env.SELF_HOSTED) {
for (let [property, column] of Object.entries(table.schema)) { for (let [property, column] of Object.entries(table.schema)) {
if (column.type === FieldTypes.ATTACHMENT) { if (column.type === FieldTypes.ATTACHMENT) {
for (let row of outputRows) { for (let row of outputRows) {

View file

@ -50,7 +50,7 @@ exports.Properties = {
} }
exports.getAPIKey = async appId => { exports.getAPIKey = async appId => {
if (env.SELF_HOSTED) { if (!env.USE_QUOTAS) {
return { apiKey: null } return { apiKey: null }
} }
return apiKeyTable.get({ primary: appId }) return apiKeyTable.get({ primary: appId })
@ -65,8 +65,7 @@ exports.getAPIKey = async appId => {
* also been reset after this call. * also been reset after this call.
*/ */
exports.update = async (apiKey, property, usage) => { exports.update = async (apiKey, property, usage) => {
// don't try validate in builder if (!env.USE_QUOTAS) {
if (!env.CLOUD || env.SELF_HOSTED) {
return return
} }
try { try {