diff --git a/lerna.json b/lerna.json
index 8f68c88cd1..7a2e88beda 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"npmClient": "yarn",
"packages": [
"packages/*"
diff --git a/packages/backend-core/cache.js b/packages/backend-core/cache.js
index 02344586a9..932fd7b901 100644
--- a/packages/backend-core/cache.js
+++ b/packages/backend-core/cache.js
@@ -1,4 +1,7 @@
+const generic = require("./src/cache/generic")
+
module.exports = {
user: require("./src/cache/user"),
app: require("./src/cache/appMetadata"),
+ ...generic,
}
diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json
index 54c0b4af17..f083320c6d 100644
--- a/packages/backend-core/package.json
+++ b/packages/backend-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/backend-core",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"description": "Budibase backend core libraries used in server and worker",
"main": "src/index.js",
"author": "Budibase",
@@ -42,8 +42,7 @@
"devDependencies": {
"ioredis-mock": "^5.5.5",
"jest": "^26.6.3",
- "pouchdb-adapter-memory": "^7.2.2",
- "pouchdb-all-dbs": "^1.0.2"
+ "pouchdb-adapter-memory": "^7.2.2"
},
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc"
}
diff --git a/packages/backend-core/src/auth.js b/packages/backend-core/src/auth.js
index f6d53522d5..b13cd932c6 100644
--- a/packages/backend-core/src/auth.js
+++ b/packages/backend-core/src/auth.js
@@ -29,7 +29,7 @@ passport.deserializeUser(async (user, done) => {
const user = await db.get(user._id)
return done(null, user)
} catch (err) {
- console.error("User not found", err)
+ console.error(`User not found`, err)
return done(null, false, { message: "User not found" })
}
})
diff --git a/packages/backend-core/src/cache/generic.js b/packages/backend-core/src/cache/generic.js
new file mode 100644
index 0000000000..b23568f8b9
--- /dev/null
+++ b/packages/backend-core/src/cache/generic.js
@@ -0,0 +1,49 @@
+const redis = require("../redis/authRedis")
+const env = require("../environment")
+const { getTenantId } = require("../context")
+
+exports.CacheKeys = {
+ CHECKLIST: "checklist",
+}
+
+exports.TTL = {
+ ONE_MINUTE: 600,
+ ONE_HOUR: 3600,
+ ONE_DAY: 86400,
+}
+
+function generateTenantKey(key) {
+ const tenantId = getTenantId()
+ return `${key}:${tenantId}`
+}
+
+exports.withCache = async (key, ttl, fetchFn) => {
+ key = generateTenantKey(key)
+ const client = await redis.getCacheClient()
+ const cachedValue = await client.get(key)
+ if (cachedValue) {
+ return cachedValue
+ }
+
+ try {
+ const fetchedValue = await fetchFn()
+
+ if (!env.isTest()) {
+ await client.store(key, fetchedValue, ttl)
+ }
+ return fetchedValue
+ } catch (err) {
+ console.error("Error fetching before cache - ", err)
+ throw err
+ }
+}
+
+exports.bustCache = async key => {
+ const client = await redis.getCacheClient()
+ try {
+ await client.delete(generateTenantKey(key))
+ } catch (err) {
+ console.error("Error busting cache - ", err)
+ throw err
+ }
+}
diff --git a/packages/backend-core/src/context/index.js b/packages/backend-core/src/context/index.js
index 20e5e26693..3abbc84596 100644
--- a/packages/backend-core/src/context/index.js
+++ b/packages/backend-core/src/context/index.js
@@ -73,7 +73,7 @@ exports.isMultiTenant = () => {
}
// used for automations, API endpoints should always be in context already
-exports.doInTenant = (tenantId, task) => {
+exports.doInTenant = (tenantId, task, { forceNew } = {}) => {
// the internal function is so that we can re-use an existing
// context - don't want to close DB on a parent context
async function internal(opts = { existing: false }) {
@@ -98,7 +98,11 @@ exports.doInTenant = (tenantId, task) => {
}
}
const using = cls.getFromContext(ContextKeys.IN_USE)
- if (using && cls.getFromContext(ContextKeys.TENANT_ID) === tenantId) {
+ if (
+ !forceNew &&
+ using &&
+ cls.getFromContext(ContextKeys.TENANT_ID) === tenantId
+ ) {
cls.setOnContext(ContextKeys.IN_USE, using + 1)
return internal({ existing: true })
} else {
@@ -135,7 +139,7 @@ const setAppTenantId = appId => {
exports.updateTenantId(appTenantId)
}
-exports.doInAppContext = (appId, task) => {
+exports.doInAppContext = (appId, task, { forceNew } = {}) => {
if (!appId) {
throw new Error("appId is required")
}
@@ -162,7 +166,7 @@ exports.doInAppContext = (appId, task) => {
}
}
const using = cls.getFromContext(ContextKeys.IN_USE)
- if (using && cls.getFromContext(ContextKeys.APP_ID) === appId) {
+ if (!forceNew && using && cls.getFromContext(ContextKeys.APP_ID) === appId) {
cls.setOnContext(ContextKeys.IN_USE, using + 1)
return internal({ existing: true })
} else {
diff --git a/packages/backend-core/src/db/index.js b/packages/backend-core/src/db/index.js
index 7d54b881b1..d179186988 100644
--- a/packages/backend-core/src/db/index.js
+++ b/packages/backend-core/src/db/index.js
@@ -3,13 +3,13 @@ const env = require("../environment")
let PouchDB
let initialised = false
+const dbList = new Set()
const put =
dbPut =>
async (doc, options = {}) => {
- const response = await dbPut(doc, options)
// TODO: add created / updated
- return response
+ return await dbPut(doc, options)
}
const checkInitialised = () => {
@@ -28,6 +28,9 @@ exports.init = opts => {
// in situations that using the function doWithDB does not work
exports.dangerousGetDB = (dbName, opts) => {
checkInitialised()
+ if (env.isTest()) {
+ dbList.add(dbName)
+ }
const db = new PouchDB(dbName, opts)
const dbPut = db.put
db.put = put(dbPut)
@@ -63,6 +66,9 @@ exports.doWithDB = async (dbName, cb, opts) => {
}
exports.allDbs = () => {
+ if (!env.isTest()) {
+ throw new Error("Cannot be used outside test environment.")
+ }
checkInitialised()
- return PouchDB.allDbs()
+ return [...dbList]
}
diff --git a/packages/backend-core/src/db/pouch.js b/packages/backend-core/src/db/pouch.js
index 9c1ada8d76..76390ac644 100644
--- a/packages/backend-core/src/db/pouch.js
+++ b/packages/backend-core/src/db/pouch.js
@@ -92,11 +92,5 @@ exports.getPouch = (opts = {}) => {
PouchDB.plugin(find)
}
- const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
- if (opts.allDbs) {
- const allDbs = require("pouchdb-all-dbs")
- allDbs(Pouch)
- }
-
- return Pouch
+ return PouchDB.defaults(POUCH_DB_DEFAULTS)
}
diff --git a/packages/backend-core/src/middleware/passport/local.js b/packages/backend-core/src/middleware/passport/local.js
index 2149bd3e18..716ebc1755 100644
--- a/packages/backend-core/src/middleware/passport/local.js
+++ b/packages/backend-core/src/middleware/passport/local.js
@@ -30,7 +30,7 @@ exports.authenticate = async function (ctx, email, password, done) {
const dbUser = await getGlobalUserByEmail(email)
if (dbUser == null) {
- return authError(done, "User not found")
+ return authError(done, `User not found: [${email}]`)
}
// check that the user is currently inactive, if this is the case throw invalid
diff --git a/packages/backend-core/src/redis/authRedis.js b/packages/backend-core/src/redis/authRedis.js
index ca5c9bae37..b9f6d8d0b0 100644
--- a/packages/backend-core/src/redis/authRedis.js
+++ b/packages/backend-core/src/redis/authRedis.js
@@ -1,18 +1,20 @@
const Client = require("./index")
const utils = require("./utils")
-let userClient, sessionClient, appClient
+let userClient, sessionClient, appClient, cacheClient
async function init() {
userClient = await new Client(utils.Databases.USER_CACHE).init()
sessionClient = await new Client(utils.Databases.SESSIONS).init()
appClient = await new Client(utils.Databases.APP_METADATA).init()
+ cacheClient = await new Client(utils.Databases.GENERIC_CACHE).init()
}
process.on("exit", async () => {
if (userClient) await userClient.finish()
if (sessionClient) await sessionClient.finish()
if (appClient) await appClient.finish()
+ if (cacheClient) await cacheClient.finish()
})
module.exports = {
@@ -34,4 +36,10 @@ module.exports = {
}
return appClient
},
+ getCacheClient: async () => {
+ if (!cacheClient) {
+ await init()
+ }
+ return cacheClient
+ },
}
diff --git a/packages/backend-core/src/redis/utils.js b/packages/backend-core/src/redis/utils.js
index 77f64f6593..90ea5c33f9 100644
--- a/packages/backend-core/src/redis/utils.js
+++ b/packages/backend-core/src/redis/utils.js
@@ -18,6 +18,7 @@ exports.Databases = {
APP_METADATA: "appMetadata",
QUERY_VARS: "queryVars",
LICENSES: "license",
+ GENERIC_CACHE: "data_cache",
}
exports.SEPARATOR = SEPARATOR
diff --git a/packages/backend-core/src/utils.js b/packages/backend-core/src/utils.js
index 5c922c42ad..e764f35803 100644
--- a/packages/backend-core/src/utils.js
+++ b/packages/backend-core/src/utils.js
@@ -197,11 +197,16 @@ exports.getBuildersCount = async () => {
return builders.length
}
-exports.saveUser = async (
+const DEFAULT_SAVE_USER = {
+ hashPassword: true,
+ requirePassword: true,
+ bulkCreate: false,
+}
+
+exports.internalSaveUser = async (
user,
tenantId,
- hashPassword = true,
- requirePassword = true
+ { hashPassword, requirePassword, bulkCreate } = DEFAULT_SAVE_USER
) => {
if (!tenantId) {
throw "No tenancy specified."
@@ -213,7 +218,10 @@ exports.saveUser = async (
let { email, password, _id } = user
// make sure another user isn't using the same email
let dbUser
- if (email) {
+ // user can't exist in bulk creation
+ if (bulkCreate) {
+ dbUser = null
+ } else if (email) {
// check budibase users inside the tenant
dbUser = await exports.getGlobalUserByEmail(email)
if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) {
@@ -267,11 +275,17 @@ exports.saveUser = async (
user.status = UserStatus.ACTIVE
}
try {
- const response = await db.put({
+ const putOpts = {
password: hashedPassword,
...user,
- })
- await tryAddTenant(tenantId, _id, email)
+ }
+ if (bulkCreate) {
+ return putOpts
+ }
+ const response = await db.put(putOpts)
+ if (env.MULTI_TENANCY) {
+ await tryAddTenant(tenantId, _id, email)
+ }
await userCache.invalidateUser(response.id)
return {
_id: response.id,
@@ -288,6 +302,19 @@ exports.saveUser = async (
})
}
+// maintained for api compat, don't want to change function signature
+exports.saveUser = async (
+ user,
+ tenantId,
+ hashPassword = true,
+ requirePassword = true
+) => {
+ return exports.internalSaveUser(user, tenantId, {
+ hashPassword,
+ requirePassword,
+ })
+}
+
/**
* Logs a user out from budibase. Re-used across account portal and builder.
*/
diff --git a/packages/backend-core/yarn.lock b/packages/backend-core/yarn.lock
index 80f292140d..db7029c4c4 100644
--- a/packages/backend-core/yarn.lock
+++ b/packages/backend-core/yarn.lock
@@ -661,11 +661,6 @@ acorn-walk@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn@^5.2.1:
- version "5.7.4"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"
- integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==
-
acorn@^7.1.1:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
@@ -701,11 +696,6 @@ ajv@^6.12.3:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
-amdefine@>=0.0.4:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
- integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
-
ansi-escapes@^4.2.1:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
@@ -800,11 +790,6 @@ assign-symbols@^1.0.0:
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
-ast-types@0.9.6:
- version "0.9.6"
- resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
- integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=
-
async@~2.1.4:
version "2.1.5"
resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc"
@@ -938,11 +923,6 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-base62@^1.1.0:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/base62/-/base62-1.2.8.tgz#1264cb0fb848d875792877479dbe8bae6bae3428"
- integrity sha512-V6YHUbjLxN1ymqNLb1DPHoU1CpfdL7d2YTIp5W3U4hhoG4hhxNmsFDs66M9EXxBiSEke5Bt5dwdfMwwZF70iLA==
-
base64-js@^1.0.2, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@@ -1259,26 +1239,6 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
-commander@^2.5.0:
- version "2.20.3"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
- integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
-
-commoner@^0.10.1:
- version "0.10.8"
- resolved "https://registry.yarnpkg.com/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5"
- integrity sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=
- dependencies:
- commander "^2.5.0"
- detective "^4.3.1"
- glob "^5.0.15"
- graceful-fs "^4.1.2"
- iconv-lite "^0.4.5"
- mkdirp "^0.5.0"
- private "^0.1.6"
- q "^1.1.2"
- recast "^0.11.17"
-
component-emitter@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
@@ -1445,11 +1405,6 @@ define-property@^2.0.2:
is-descriptor "^1.0.2"
isobject "^3.0.1"
-defined@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
- integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
-
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -1465,14 +1420,6 @@ detect-newline@^3.0.0:
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
-detective@^4.3.1:
- version "4.7.1"
- resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e"
- integrity sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==
- dependencies:
- acorn "^5.2.1"
- defined "^1.0.0"
-
diff-sequences@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1"
@@ -1577,15 +1524,6 @@ error-ex@^1.3.1:
dependencies:
is-arrayish "^0.2.1"
-es3ify@^0.2.2:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/es3ify/-/es3ify-0.2.2.tgz#5dae3e650e5be3684b88066513d528d092629862"
- integrity sha1-Xa4+ZQ5b42hLiAZlE9Uo0JJimGI=
- dependencies:
- esprima "^2.7.1"
- jstransform "~11.0.0"
- through "~2.3.4"
-
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
@@ -1613,26 +1551,11 @@ escodegen@^2.0.0:
optionalDependencies:
source-map "~0.6.1"
-esprima-fb@^15001.1.0-dev-harmony-fb:
- version "15001.1.0-dev-harmony-fb"
- resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-15001.1.0-dev-harmony-fb.tgz#30a947303c6b8d5e955bee2b99b1d233206a6901"
- integrity sha1-MKlHMDxrjV6VW+4rmbHSMyBqaQE=
-
-esprima@^2.7.1:
- version "2.7.3"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
- integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=
-
esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-esprima@~3.1.0:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
- integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
-
estraverse@^5.2.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
@@ -1950,17 +1873,6 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
-glob@^5.0.15:
- version "5.0.15"
- resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
- integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=
- dependencies:
- inflight "^1.0.4"
- inherits "2"
- minimatch "2 || 3"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
version "7.2.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
@@ -2004,7 +1916,7 @@ googleapis@^16.0.0:
google-auth-library "~0.10.0"
string-template "~1.0.0"
-graceful-fs@^4.1.2, graceful-fs@^4.2.4:
+graceful-fs@^4.2.4:
version "4.2.8"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
@@ -2170,7 +2082,7 @@ human-signals@^1.1.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
-iconv-lite@0.4.24, iconv-lite@^0.4.5:
+iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -2993,17 +2905,6 @@ jsprim@^1.2.2:
json-schema "0.2.3"
verror "1.3.6"
-jstransform@~11.0.0:
- version "11.0.3"
- resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-11.0.3.tgz#09a78993e0ae4d4ef4487f6155a91f6190cb4223"
- integrity sha1-CaeJk+CuTU70SH9hVakfYZDLQiM=
- dependencies:
- base62 "^1.1.0"
- commoner "^0.10.1"
- esprima-fb "^15001.1.0-dev-harmony-fb"
- object-assign "^2.0.0"
- source-map "^0.4.2"
-
jwa@^1.1.4:
version "1.1.5"
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.1.5.tgz#a0552ce0220742cd52e153774a32905c30e756e5"
@@ -3392,7 +3293,7 @@ mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-"minimatch@2 || 3", minimatch@^3.0.4:
+minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -3417,13 +3318,6 @@ mkdirp-classic@^0.5.2:
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
-mkdirp@^0.5.0:
- version "0.5.5"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
- integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
- dependencies:
- minimist "^1.2.5"
-
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -3586,11 +3480,6 @@ oauth@0.9.x, oauth@^0.9.15:
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
-object-assign@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa"
- integrity sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=
-
object-copy@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
@@ -3923,17 +3812,6 @@ pouchdb-adapter-utils@7.2.2:
pouchdb-merge "7.2.2"
pouchdb-utils "7.2.2"
-pouchdb-all-dbs@^1.0.2:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/pouchdb-all-dbs/-/pouchdb-all-dbs-1.1.1.tgz#85f04a39cafda52497ec49abf1c93bb5e72813f6"
- integrity sha512-UUnsdmcnRSQ8MAOYSJjfTwKkQNb/6fvOfd/f7dNNivWZ2YDYVuMfgw1WQdL634yEtcXTxAENZ/EyLRdzPCB41A==
- dependencies:
- argsarray "0.0.1"
- es3ify "^0.2.2"
- inherits "~2.0.1"
- pouchdb-promise "6.4.3"
- tiny-queue "^0.2.0"
-
pouchdb-binary-utils@7.2.2:
version "7.2.2"
resolved "https://registry.yarnpkg.com/pouchdb-binary-utils/-/pouchdb-binary-utils-7.2.2.tgz#0690b348052c543b1e67f032f47092ca82bcb10e"
@@ -4010,7 +3888,7 @@ pouchdb-merge@7.2.2:
resolved "https://registry.yarnpkg.com/pouchdb-merge/-/pouchdb-merge-7.2.2.tgz#940d85a2b532d6a93a6cab4b250f5648511bcc16"
integrity sha512-6yzKJfjIchBaS7Tusuk8280WJdESzFfQ0sb4jeMUNnrqs4Cx3b0DIEOYTRRD9EJDM+je7D3AZZ4AT0tFw8gb4A==
-pouchdb-promise@6.4.3, pouchdb-promise@^6.0.4:
+pouchdb-promise@^6.0.4:
version "6.4.3"
resolved "https://registry.yarnpkg.com/pouchdb-promise/-/pouchdb-promise-6.4.3.tgz#74516f4acf74957b54debd0fb2c0e5b5a68ca7b3"
integrity sha512-ruJaSFXwzsxRHQfwNHjQfsj58LBOY1RzGzde4PM5CWINZwFjCQAhZwfMrch2o/0oZT6d+Xtt0HTWhq35p3b0qw==
@@ -4093,11 +3971,6 @@ pretty-format@^26.6.2:
ansi-styles "^4.0.0"
react-is "^17.0.1"
-private@^0.1.6, private@~0.1.5:
- version "0.1.8"
- resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
- integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
-
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@@ -4144,11 +4017,6 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-q@^1.1.2:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
- integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
-
qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
@@ -4230,16 +4098,6 @@ readline-sync@^1.4.9:
resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b"
integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==
-recast@^0.11.17:
- version "0.11.23"
- resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
- integrity sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=
- dependencies:
- ast-types "0.9.6"
- esprima "~3.1.0"
- private "~0.1.5"
- source-map "~0.5.0"
-
redis-commands@1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
@@ -4597,14 +4455,7 @@ source-map-url@^0.4.0:
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
-source-map@^0.4.2:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
- integrity sha1-66T12pwNyZneaAMti092FzZSA2s=
- dependencies:
- amdefine ">=0.0.4"
-
-source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.0:
+source-map@^0.5.0, source-map@^0.5.6:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -4884,16 +4735,6 @@ through2@^2.0.0, through2@^2.0.2, through2@^2.0.3:
readable-stream "~2.3.6"
xtend "~4.0.1"
-through@~2.3.4:
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
- integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
-
-tiny-queue@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046"
- integrity sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY=
-
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
diff --git a/packages/bbui/package.json b/packages/bbui/package.json
index e4f527555e..456555e546 100644
--- a/packages/bbui/package.json
+++ b/packages/bbui/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"license": "MPL-2.0",
"svelte": "src/index.js",
"module": "dist/bbui.es.js",
@@ -38,7 +38,7 @@
],
"dependencies": {
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
- "@budibase/string-templates": "^1.0.167-alpha.8",
+ "@budibase/string-templates": "^1.0.176-alpha.0",
"@spectrum-css/actionbutton": "^1.0.1",
"@spectrum-css/actiongroup": "^1.0.1",
"@spectrum-css/avatar": "^3.0.2",
diff --git a/packages/builder/package.json b/packages/builder/package.json
index 367d23505a..4f333c7cd5 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/builder",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"license": "GPL-3.0",
"private": true,
"scripts": {
@@ -69,10 +69,10 @@
}
},
"dependencies": {
- "@budibase/bbui": "^1.0.167-alpha.8",
- "@budibase/client": "^1.0.167-alpha.8",
- "@budibase/frontend-core": "^1.0.167-alpha.8",
- "@budibase/string-templates": "^1.0.167-alpha.8",
+ "@budibase/bbui": "^1.0.176-alpha.0",
+ "@budibase/client": "^1.0.176-alpha.0",
+ "@budibase/frontend-core": "^1.0.176-alpha.0",
+ "@budibase/string-templates": "^1.0.176-alpha.0",
"@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1",
diff --git a/packages/builder/src/builderStore/store/automation/index.js b/packages/builder/src/builderStore/store/automation/index.js
index 84e6033439..5252d4b06a 100644
--- a/packages/builder/src/builderStore/store/automation/index.js
+++ b/packages/builder/src/builderStore/store/automation/index.js
@@ -105,9 +105,7 @@ const automationActions = store => ({
},
select: automation => {
store.update(state => {
- let testResults = state.selectedAutomation?.testResults
state.selectedAutomation = new Automation(cloneDeep(automation))
- state.selectedAutomation.testResults = testResults
state.selectedBlock = null
return state
})
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte
index 505a0b9aca..3e58b25ff6 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowChart.svelte
@@ -14,7 +14,6 @@
} from "@budibase/bbui"
export let automation
-
let testDataModal
let blocks
let confirmDeleteDialog
@@ -41,66 +40,70 @@
-
-
-
-
{automation.name}
-
-
+
+ {automation.name}
+
+
+
+
+
+
+
+
{
+ testDataModal.show()
+ }}
+ icon="MultipleCheck"
+ size="M">Run test
+
{
- testDataModal.show()
+ $automationStore.selectedAutomation.automation.showTestPanel = true
}}
- icon="MultipleCheck"
- size="M">Run testTest Details
- {#each blocks as block, idx (block.id)}
-
- {#if block.stepId !== "LOOP"}
-
- {/if}
-
- {/each}
-
- Are you sure you wish to delete the automation
- {automation.name}?
- This action cannot be undone.
-
-
-
-
-
+
+ {#each blocks as block, idx (block.id)}
+
+ {#if block.stepId !== "LOOP"}
+
+ {/if}
+
+ {/each}
+
+
+ Are you sure you wish to delete the automation
+ {automation.name}?
+ This action cannot be undone.
+
+
+
+
+
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ResultsModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ResultsModal.svelte
deleted file mode 100644
index 9662bc8ade..0000000000
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/ResultsModal.svelte
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-
-
-
- {#if testResult[0].outputs.iterations}
-
-
-
-
-
-
- {/if}
-
- {
- inputToggled = !inputToggled
- }}
- class="toggle splitHeader"
- >
-
-
- {#if inputToggled}
-
- {:else}
-
- {/if}
-
-
- {#if inputToggled}
-
-
-
- {/if}
-
- {
- outputToggled = !outputToggled
- }}
- class="toggle splitHeader"
- >
-
-
- {#if outputToggled}
-
- {:else}
-
- {/if}
-
-
- {#if outputToggled}
-
-
-
- {/if}
-
-
-
diff --git a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte
index ffd59b4e6a..fecd0fcc7e 100644
--- a/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte
+++ b/packages/builder/src/components/automation/AutomationBuilder/FlowChart/TestDataModal.svelte
@@ -51,6 +51,7 @@
$automationStore.selectedAutomation?.automation,
testData
)
+ $automationStore.selectedAutomation.automation.showTestPanel = true
} catch (error) {
notifications.error("Error testing notification")
}
diff --git a/packages/builder/src/components/automation/AutomationBuilder/TestPanel.svelte b/packages/builder/src/components/automation/AutomationBuilder/TestPanel.svelte
new file mode 100644
index 0000000000..8c38d8a689
--- /dev/null
+++ b/packages/builder/src/components/automation/AutomationBuilder/TestPanel.svelte
@@ -0,0 +1,146 @@
+
+
+
+
+
+ {
+ $automationStore.selectedAutomation.automation.showTestPanel = false
+ }}
+ hoverable
+ name="Close"
+ />
+
+
+
+
+
+
+ {#each blocks as block, idx}
+
+ {#if block.stepId !== "LOOP"}
+
+ {#if showParameters && showParameters[block.id]}
+
+ {#if testResults?.[idx]?.outputs.iterations}
+
+
+
+
+
+
+ {/if}
+
+
+ {/if}
+ {/if}
+
+ {#if blocks.length - 1 !== idx}
+
+ {/if}
+ {/each}
+
+
+
diff --git a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte
index 841acb22c0..a713067bbe 100644
--- a/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte
+++ b/packages/builder/src/pages/builder/app/[application]/automate/_layout.svelte
@@ -4,7 +4,12 @@
import AutomationPanel from "components/automation/AutomationPanel/AutomationPanel.svelte"
import CreateAutomationModal from "components/automation/AutomationPanel/CreateAutomationModal.svelte"
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
- $: automation = $automationStore.automations[0]
+ import TestPanel from "components/automation/AutomationBuilder/TestPanel.svelte"
+
+ $: automation =
+ $automationStore.selectedAutomation?.automation ||
+ $automationStore.automations[0]
+
let modal
let webhookModal
@@ -39,6 +44,12 @@
{/if}
+
+ {#if automation?.showTestPanel}
+
+
+
+ {/if}
@@ -52,7 +63,9 @@
flex: 1 1 auto;
height: 0;
display: grid;
- grid-template-columns: 260px minmax(510px, 1fr);
+ grid-auto-flow: column dense;
+ grid-template-columns: 260px minmax(510px, 1fr) fit-content(500px);
+ overflow: hidden;
}
.nav {
@@ -64,17 +77,18 @@
border-right: var(--border-light);
background-color: var(--background);
padding-bottom: 60px;
+ overflow: hidden;
}
.content {
position: relative;
- padding: var(--spacing-l) 40px;
+ padding-top: var(--spacing-l);
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
gap: var(--spacing-l);
- overflow: hidden;
+ overflow: auto;
}
.centered {
top: 0;
@@ -92,4 +106,17 @@
.main {
width: 300px;
}
+
+ .setup {
+ padding-top: var(--spectrum-global-dimension-size-200);
+ border-left: var(--border-light);
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: stretch;
+ gap: var(--spacing-l);
+ background-color: var(--background);
+ grid-column: 3;
+ overflow: auto;
+ }
diff --git a/packages/builder/src/pages/builder/auth/login.svelte b/packages/builder/src/pages/builder/auth/login.svelte
index d9151b4342..c2ec547e38 100644
--- a/packages/builder/src/pages/builder/auth/login.svelte
+++ b/packages/builder/src/pages/builder/auth/login.svelte
@@ -28,7 +28,7 @@
async function login() {
try {
await auth.login({
- username,
+ username: username.trim(),
password,
})
if ($auth?.user?.forceResetPassword) {
@@ -80,7 +80,9 @@
/>
-
+
$goto("./forgot")}>
Forgot password?
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 0fbc5422a2..d4cb7cc4bd 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/cli",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js",
"bin": {
diff --git a/packages/client/package.json b/packages/client/package.json
index 794fef2c15..dfa8aba29c 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/client",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"license": "MPL-2.0",
"module": "dist/budibase-client.js",
"main": "dist/budibase-client.js",
@@ -19,9 +19,9 @@
"dev:builder": "rollup -cw"
},
"dependencies": {
- "@budibase/bbui": "^1.0.167-alpha.8",
- "@budibase/frontend-core": "^1.0.167-alpha.8",
- "@budibase/string-templates": "^1.0.167-alpha.8",
+ "@budibase/bbui": "^1.0.176-alpha.0",
+ "@budibase/frontend-core": "^1.0.176-alpha.0",
+ "@budibase/string-templates": "^1.0.176-alpha.0",
"@spectrum-css/button": "^3.0.3",
"@spectrum-css/card": "^3.0.3",
"@spectrum-css/divider": "^1.0.3",
diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json
index 56cb0ed958..16fbd60728 100644
--- a/packages/frontend-core/package.json
+++ b/packages/frontend-core/package.json
@@ -1,12 +1,12 @@
{
"name": "@budibase/frontend-core",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase",
"license": "MPL-2.0",
"svelte": "src/index.js",
"dependencies": {
- "@budibase/bbui": "^1.0.167-alpha.8",
+ "@budibase/bbui": "^1.0.176-alpha.0",
"lodash": "^4.17.21",
"svelte": "^3.46.2"
}
diff --git a/packages/server/Dockerfile b/packages/server/Dockerfile
index 0ef0fe4244..e5063a88ed 100644
--- a/packages/server/Dockerfile
+++ b/packages/server/Dockerfile
@@ -16,6 +16,7 @@ ENV BUDIBASE_ENVIRONMENT=PRODUCTION
# copy files and install dependencies
COPY . ./
RUN yarn
+RUN yarn global add pm2
RUN yarn build
# Install client for oracle datasource
@@ -28,4 +29,5 @@ EXPOSE 4001
# due to this causing yarn to stop installing dev dependencies
# which are actually needed to get this environment up and running
ENV NODE_ENV=production
-CMD ["yarn", "run:docker"]
+ENV CLUSTER_MODE=${CLUSTER_MODE}
+CMD ["./docker_run.sh"]
diff --git a/packages/server/__mocks__/pg.ts b/packages/server/__mocks__/pg.ts
index 44aeabcb38..110933ad52 100644
--- a/packages/server/__mocks__/pg.ts
+++ b/packages/server/__mocks__/pg.ts
@@ -14,7 +14,9 @@ module PgMock {
function Client() {}
Client.prototype.query = query
- Client.prototype.end = jest.fn()
+ Client.prototype.end = jest.fn(cb => {
+ if (cb) cb()
+ })
Client.prototype.connect = jest.fn()
Client.prototype.release = jest.fn()
diff --git a/packages/server/docker_run.sh b/packages/server/docker_run.sh
new file mode 100755
index 0000000000..0045fe0c44
--- /dev/null
+++ b/packages/server/docker_run.sh
@@ -0,0 +1,5 @@
+if [ -z $CLUSTER_MODE ]; then
+ yarn run:docker
+else
+ yarn run:docker:cluster
+fi
diff --git a/packages/server/package.json b/packages/server/package.json
index 6216ee48d3..f603e7616a 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/server",
"email": "hi@budibase.com",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"description": "Budibase Web Server",
"main": "src/index.ts",
"repository": {
@@ -18,6 +18,7 @@
"build:docker": "yarn run predocker && docker build . -t app-service --label version=$BUDIBASE_RELEASE_VERSION",
"build:docs": "node ./scripts/docs/generate.js open",
"run:docker": "node dist/index.js",
+ "run:docker:cluster": "pm2-runtime start pm2.config.js",
"dev:stack:up": "node scripts/dev/manage.js up",
"dev:stack:down": "node scripts/dev/manage.js down",
"dev:stack:nuke": "node scripts/dev/manage.js nuke",
@@ -69,10 +70,10 @@
"license": "GPL-3.0",
"dependencies": {
"@apidevtools/swagger-parser": "^10.0.3",
- "@budibase/backend-core": "^1.0.167-alpha.8",
- "@budibase/client": "^1.0.167-alpha.8",
- "@budibase/pro": "1.0.167-alpha.8",
- "@budibase/string-templates": "^1.0.167-alpha.8",
+ "@budibase/backend-core": "^1.0.176-alpha.0",
+ "@budibase/client": "^1.0.176-alpha.0",
+ "@budibase/pro": "1.0.176-alpha.0",
+ "@budibase/string-templates": "^1.0.176-alpha.0",
"@bull-board/api": "^3.7.0",
"@bull-board/koa": "^3.7.0",
"@elastic/elasticsearch": "7.10.0",
diff --git a/packages/server/pm2.config.js b/packages/server/pm2.config.js
new file mode 100644
index 0000000000..33829f327c
--- /dev/null
+++ b/packages/server/pm2.config.js
@@ -0,0 +1,9 @@
+module.exports = {
+ apps: [
+ {
+ script: "dist/index.js",
+ instances: "max",
+ exec_mode: "cluster",
+ },
+ ],
+}
diff --git a/packages/server/scripts/load/users.js b/packages/server/scripts/load/users.js
new file mode 100644
index 0000000000..3bc8056986
--- /dev/null
+++ b/packages/server/scripts/load/users.js
@@ -0,0 +1,97 @@
+// get the JWT secret etc
+require("../../src/environment")
+require("@budibase/backend-core").init()
+const {
+ getProdAppID,
+ generateGlobalUserID,
+} = require("@budibase/backend-core/db")
+const { doInTenant, getGlobalDB } = require("@budibase/backend-core/tenancy")
+const { internalSaveUser } = require("@budibase/backend-core/utils")
+const { publicApiUserFix } = require("../../src/utilities/users")
+const { hash } = require("@budibase/backend-core/utils")
+
+const USER_LOAD_NUMBER = 10000
+const BATCH_SIZE = 200
+const PASSWORD = "test"
+const TENANT_ID = "default"
+
+const APP_ID = process.argv[2]
+
+const words = [
+ "test",
+ "testing",
+ "budi",
+ "mail",
+ "age",
+ "risk",
+ "load",
+ "uno",
+ "arm",
+ "leg",
+ "pen",
+ "glass",
+ "box",
+ "chicken",
+ "bottle",
+]
+
+if (!APP_ID) {
+ console.error("Must supply app ID as first CLI option!")
+ process.exit(-1)
+}
+
+const WORD_1 = words[Math.floor(Math.random() * words.length)]
+const WORD_2 = words[Math.floor(Math.random() * words.length)]
+let HASHED_PASSWORD
+
+function generateUser(count) {
+ return {
+ _id: generateGlobalUserID(),
+ password: HASHED_PASSWORD,
+ email: `${WORD_1}${count}@${WORD_2}.com`,
+ roles: {
+ [getProdAppID(APP_ID)]: "BASIC",
+ },
+ status: "active",
+ forceResetPassword: false,
+ firstName: "John",
+ lastName: "Smith",
+ }
+}
+
+async function run() {
+ HASHED_PASSWORD = await hash(PASSWORD)
+ return doInTenant(TENANT_ID, async () => {
+ const db = getGlobalDB()
+ for (let i = 0; i < USER_LOAD_NUMBER; i += BATCH_SIZE) {
+ let userSavePromises = []
+ for (let j = 0; j < BATCH_SIZE; j++) {
+ // like the public API
+ const ctx = publicApiUserFix({
+ request: {
+ body: generateUser(i + j),
+ },
+ })
+ userSavePromises.push(
+ internalSaveUser(ctx.request.body, TENANT_ID, {
+ hashPassword: false,
+ requirePassword: true,
+ bulkCreate: true,
+ })
+ )
+ }
+ const users = await Promise.all(userSavePromises)
+ await db.bulkDocs(users)
+ console.log(`${i + BATCH_SIZE} users have been created.`)
+ }
+ })
+}
+
+run()
+ .then(() => {
+ console.log(`Generated ${USER_LOAD_NUMBER} users!`)
+ })
+ .catch(err => {
+ console.error("Failed for reason: ", err)
+ process.exit(-1)
+ })
diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts
index 61ba794e44..be0e2997e0 100644
--- a/packages/server/src/api/controllers/application.ts
+++ b/packages/server/src/api/controllers/application.ts
@@ -25,6 +25,7 @@ const {
import { BASE_LAYOUTS } from "../../constants/layouts"
import { cloneDeep } from "lodash/fp"
const { processObject } = require("@budibase/string-templates")
+const { CacheKeys, bustCache } = require("@budibase/backend-core/cache")
const {
getAllApps,
isDevAppID,
@@ -326,6 +327,7 @@ const appPostCreate = async (ctx: any, appId: string) => {
export const create = async (ctx: any) => {
const newApplication = await quotas.addApp(() => performAppCreate(ctx))
await appPostCreate(ctx, newApplication.appId)
+ await bustCache(CacheKeys.CHECKLIST)
ctx.body = newApplication
ctx.status = 200
}
@@ -449,6 +451,15 @@ export const destroy = async (ctx: any) => {
}
export const sync = async (ctx: any, next: any) => {
+ if (env.DISABLE_AUTO_PROD_APP_SYNC) {
+ ctx.status = 200
+ ctx.body = {
+ message:
+ "App sync disabled. You can reenable with the DISABLE_AUTO_PROD_APP_SYNC environment variable.",
+ }
+ return next()
+ }
+
const appId = ctx.params.appId
if (!isDevAppID(appId)) {
ctx.throw(400, "This action cannot be performed for production apps")
diff --git a/packages/server/src/api/controllers/public/users.ts b/packages/server/src/api/controllers/public/users.ts
index f199dcb761..129d2c883f 100644
--- a/packages/server/src/api/controllers/public/users.ts
+++ b/packages/server/src/api/controllers/public/users.ts
@@ -4,30 +4,9 @@ import {
readGlobalUser,
saveGlobalUser,
} from "../../../utilities/workerRequests"
+import { publicApiUserFix } from "../../../utilities/users"
import { search as stringSearch } from "./utils"
-const { getProdAppID } = require("@budibase/backend-core/db")
-
-function fixUser(ctx: any) {
- if (!ctx.request.body) {
- return ctx
- }
- if (!ctx.request.body._id && ctx.params.userId) {
- ctx.request.body._id = ctx.params.userId
- }
- if (!ctx.request.body.roles) {
- ctx.request.body.roles = {}
- } else {
- const newRoles: { [key: string]: string } = {}
- for (let [appId, role] of Object.entries(ctx.request.body.roles)) {
- // @ts-ignore
- newRoles[getProdAppID(appId)] = role
- }
- ctx.request.body.roles = newRoles
- }
- return ctx
-}
-
function getUser(ctx: any, userId?: string) {
if (userId) {
ctx.params = { userId }
@@ -45,7 +24,7 @@ export async function search(ctx: any, next: any) {
}
export async function create(ctx: any, next: any) {
- const response = await saveGlobalUser(fixUser(ctx))
+ const response = await saveGlobalUser(publicApiUserFix(ctx))
ctx.body = await getUser(ctx, response._id)
await next()
}
@@ -61,7 +40,7 @@ export async function update(ctx: any, next: any) {
...ctx.request.body,
_rev: user._rev,
}
- const response = await saveGlobalUser(fixUser(ctx))
+ const response = await saveGlobalUser(publicApiUserFix(ctx))
ctx.body = await getUser(ctx, response._id)
await next()
}
diff --git a/packages/server/src/environment.js b/packages/server/src/environment.js
index 45b8f68a49..4d01f9ef00 100644
--- a/packages/server/src/environment.js
+++ b/packages/server/src/environment.js
@@ -1,3 +1,5 @@
+const { join } = require("path")
+
function isTest() {
return (
process.env.NODE_ENV === "jest" ||
@@ -20,7 +22,9 @@ function isCypress() {
let LOADED = false
if (!LOADED && isDev() && !isTest()) {
- require("dotenv").config()
+ require("dotenv").config({
+ path: join(__dirname, "..", ".env"),
+ })
LOADED = true
}
@@ -55,6 +59,7 @@ module.exports = {
BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT,
DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
TEMPLATE_REPOSITORY: process.env.TEMPLATE_REPOSITORY || "app",
+ DISABLE_AUTO_PROD_APP_SYNC: process.env.DISABLE_AUTO_PROD_APP_SYNC,
// minor
SALT_ROUNDS: process.env.SALT_ROUNDS,
LOGGER: process.env.LOGGER,
diff --git a/packages/server/src/integrations/postgres.ts b/packages/server/src/integrations/postgres.ts
index 430a3f3461..220f35dae5 100644
--- a/packages/server/src/integrations/postgres.ts
+++ b/packages/server/src/integrations/postgres.ts
@@ -136,7 +136,7 @@ module PostgresModule {
: undefined,
}
this.client = new Client(newConfig)
- this.setSchema()
+ this.open = false
}
getBindingIdentifier(): string {
@@ -147,7 +147,34 @@ module PostgresModule {
return parts.join(" || ")
}
+ async openConnection() {
+ await this.client.connect()
+ if (!this.config.schema) {
+ this.config.schema = "public"
+ }
+ this.client.query(`SET search_path TO ${this.config.schema}`)
+ this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${this.config.schema}'`
+ this.open = true
+ }
+
+ closeConnection() {
+ const pg = this
+ return new Promise((resolve, reject) => {
+ this.client.end((err: any) => {
+ pg.open = false
+ if (err) {
+ reject(err)
+ } else {
+ resolve()
+ }
+ })
+ })
+ }
+
async internalQuery(query: SqlQuery, close: boolean = true) {
+ if (!this.open) {
+ await this.openConnection()
+ }
const client = this.client
this.index = 1
// need to handle a specific issue with json data types in postgres,
@@ -164,23 +191,16 @@ module PostgresModule {
try {
return await client.query(query.sql, query.bindings || [])
} catch (err) {
- await this.client.end()
+ await this.closeConnection()
// @ts-ignore
throw new Error(err)
} finally {
- if (close) await this.client.end()
+ if (close) {
+ await this.closeConnection()
+ }
}
}
- async setSchema() {
- await this.client.connect()
- if (!this.config.schema) {
- this.config.schema = "public"
- }
- this.client.query(`SET search_path TO ${this.config.schema}`)
- this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${this.config.schema}'`
- }
-
/**
* Fetches the tables from the postgres table and assigns them to the datasource.
* @param {*} datasourceId - datasourceId to fetch
@@ -188,6 +208,7 @@ module PostgresModule {
*/
async buildSchema(datasourceId: string, entities: Record) {
let tableKeys: { [key: string]: string[] } = {}
+ await this.openConnection()
try {
const primaryKeysResponse = await this.client.query(
this.PRIMARY_KEYS_SQL
@@ -251,7 +272,7 @@ module PostgresModule {
// @ts-ignore
throw new Error(err)
} finally {
- await this.client.end()
+ await this.closeConnection()
}
}
@@ -283,7 +304,7 @@ module PostgresModule {
for (let query of input) {
responses.push(await this.internalQuery(query, false))
}
- await this.client.end()
+ await this.closeConnection()
return responses
} else {
const response = await this.internalQuery(input)
diff --git a/packages/server/src/utilities/users.js b/packages/server/src/utilities/users.js
index b3601986d8..e769441322 100644
--- a/packages/server/src/utilities/users.js
+++ b/packages/server/src/utilities/users.js
@@ -1,6 +1,7 @@
const { InternalTables } = require("../db/utils")
const { getGlobalUser } = require("../utilities/global")
const { getAppDB } = require("@budibase/backend-core/context")
+const { getProdAppID } = require("@budibase/backend-core/db")
exports.getFullUser = async (ctx, userId) => {
const global = await getGlobalUser(userId)
@@ -22,3 +23,23 @@ exports.getFullUser = async (ctx, userId) => {
_id: userId,
}
}
+
+exports.publicApiUserFix = ctx => {
+ if (!ctx.request.body) {
+ return ctx
+ }
+ if (!ctx.request.body._id && ctx.params.userId) {
+ ctx.request.body._id = ctx.params.userId
+ }
+ if (!ctx.request.body.roles) {
+ ctx.request.body.roles = {}
+ } else {
+ const newRoles = {}
+ for (let [appId, role] of Object.entries(ctx.request.body.roles)) {
+ // @ts-ignore
+ newRoles[getProdAppID(appId)] = role
+ }
+ ctx.request.body.roles = newRoles
+ }
+ return ctx
+}
diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock
index 4184ef63e9..0bcd33f0d1 100644
--- a/packages/server/yarn.lock
+++ b/packages/server/yarn.lock
@@ -1014,10 +1014,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-"@budibase/backend-core@1.0.167-alpha.8":
- version "1.0.167-alpha.8"
- resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.167-alpha.8.tgz#e663928587cb3ec90d06b3c5766fce61c11e93a6"
- integrity sha512-J4LtucuaJJd5lAs9mV6Rt9D5dCZhKNrrKajnFTXqOrjsyw0jsIfN2ku8ClV0C9J3NA3wAu2zjpfDaKSnNfg2OQ==
+"@budibase/backend-core@1.0.176-alpha.0":
+ version "1.0.176-alpha.0"
+ resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.176-alpha.0.tgz#eca4d405f6a3feadc231ce851323005762b83b88"
+ integrity sha512-7GFAO499/rX/066jpChEH2CwOo+UI88MrZcceWqfbv3hBcV4nDUtVFUtzG63z74vQb9SHi0B15/qOYB5mzVQLw==
dependencies:
"@techpass/passport-openidconnect" "^0.3.0"
aws-sdk "^2.901.0"
@@ -1092,12 +1092,12 @@
svelte-flatpickr "^3.2.3"
svelte-portal "^1.0.0"
-"@budibase/pro@1.0.167-alpha.8":
- version "1.0.167-alpha.8"
- resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.167-alpha.8.tgz#dfcecb85550bc07a89b8e0bd2dbff13543d99117"
- integrity sha512-MPEtYLnHfFchBzQs5nZSAavCANh32hd1VSXUB5KJSkEdtpQ9eoJ+hOGThrM9PJtTVX3Jq31nsg0/PmUkswBdAQ==
+"@budibase/pro@1.0.176-alpha.0":
+ version "1.0.176-alpha.0"
+ resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.176-alpha.0.tgz#416522800ef47b6ccc9e8bfc0e8d722db54f5c68"
+ integrity sha512-oe/HQsDpGZ3HO7t0TPqfKfh/FjZw5f9V22LxS45WXoOgL8b66U2WGwCaN7iF/zzxgPXlZ3h8TSHo9ai9d2UOgA==
dependencies:
- "@budibase/backend-core" "1.0.167-alpha.8"
+ "@budibase/backend-core" "1.0.176-alpha.0"
node-fetch "^2.6.1"
"@budibase/standard-components@^0.9.139":
diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json
index f94cf031a4..09b84276c1 100644
--- a/packages/string-templates/package.json
+++ b/packages/string-templates/package.json
@@ -1,6 +1,6 @@
{
"name": "@budibase/string-templates",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs",
"module": "dist/bundle.mjs",
diff --git a/packages/worker/Dockerfile b/packages/worker/Dockerfile
index 614a724ab6..b73efcc4a1 100644
--- a/packages/worker/Dockerfile
+++ b/packages/worker/Dockerfile
@@ -10,6 +10,7 @@ WORKDIR /app
# copy files and install dependencies
COPY . ./
RUN yarn
+RUN yarn global add pm2
EXPOSE 4001
@@ -17,4 +18,5 @@ EXPOSE 4001
# due to this causing yarn to stop installing dev dependencies
# which are actually needed to get this environment up and running
ENV NODE_ENV=production
-CMD ["yarn", "run:docker"]
+ENV CLUSTER_MODE=${CLUSTER_MODE}
+CMD ["./docker_run.sh"]
diff --git a/packages/worker/docker_run.sh b/packages/worker/docker_run.sh
new file mode 100755
index 0000000000..20694e5df0
--- /dev/null
+++ b/packages/worker/docker_run.sh
@@ -0,0 +1,5 @@
+if [[ -z $CLUSTER_MODE ]]; then
+ yarn run:docker
+else
+ yarn run:docker:cluster
+fi
diff --git a/packages/worker/package.json b/packages/worker/package.json
index ee391811f9..5bf4897955 100644
--- a/packages/worker/package.json
+++ b/packages/worker/package.json
@@ -1,7 +1,7 @@
{
"name": "@budibase/worker",
"email": "hi@budibase.com",
- "version": "1.0.167-alpha.8",
+ "version": "1.0.176-alpha.0",
"description": "Budibase background service",
"main": "src/index.ts",
"repository": {
@@ -15,6 +15,7 @@
"build": "rimraf dist/ && tsc",
"postbuild": "copyfiles -u 1 src/**/*.hbs dist/",
"run:docker": "node dist/index.js",
+ "run:docker:cluster": "pm2-runtime start pm2.config.js",
"build:docker": "docker build . -t worker-service --label version=$BUDIBASE_RELEASE_VERSION",
"dev:stack:init": "node ./scripts/dev/manage.js init",
"dev:builder": "npm run dev:stack:init && nodemon",
@@ -31,9 +32,9 @@
"author": "Budibase",
"license": "GPL-3.0",
"dependencies": {
- "@budibase/backend-core": "^1.0.167-alpha.8",
- "@budibase/pro": "1.0.167-alpha.8",
- "@budibase/string-templates": "^1.0.167-alpha.8",
+ "@budibase/backend-core": "^1.0.176-alpha.0",
+ "@budibase/pro": "1.0.176-alpha.0",
+ "@budibase/string-templates": "^1.0.176-alpha.0",
"@koa/router": "^8.0.0",
"@sentry/node": "6.17.7",
"@techpass/passport-openidconnect": "^0.3.0",
diff --git a/packages/worker/pm2.config.js b/packages/worker/pm2.config.js
new file mode 100644
index 0000000000..b5fb1880ef
--- /dev/null
+++ b/packages/worker/pm2.config.js
@@ -0,0 +1,9 @@
+module.exports = {
+ apps: [
+ {
+ script: "./dist/index.js",
+ instances: "max",
+ exec_mode: "cluster",
+ },
+ ],
+}
diff --git a/packages/worker/src/api/controllers/global/configs.js b/packages/worker/src/api/controllers/global/configs.js
index 2562dd4e2e..df3326ef26 100644
--- a/packages/worker/src/api/controllers/global/configs.js
+++ b/packages/worker/src/api/controllers/global/configs.js
@@ -14,6 +14,11 @@ const {
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
const env = require("../../../environment")
const { googleCallbackUrl, oidcCallbackUrl } = require("./auth")
+const {
+ withCache,
+ CacheKeys,
+ bustCache,
+} = require("@budibase/backend-core/cache")
const BB_TENANT_CDN = "https://tenants.cdn.budi.live"
@@ -43,6 +48,7 @@ exports.save = async function (ctx) {
try {
const response = await db.put(ctx.request.body)
+ await bustCache(CacheKeys.CHECKLIST)
ctx.body = {
type,
_id: response.id,
@@ -249,58 +255,62 @@ exports.configChecklist = async function (ctx) {
const tenantId = getTenantId()
try {
- // TODO: Watch get started video
+ ctx.body = await withCache(
+ CacheKeys.CHECKLIST,
+ env.CHECKLIST_CACHE_TTL,
+ async () => {
+ let apps = []
+ if (!env.MULTI_TENANCY || tenantId) {
+ // Apps exist
+ apps = await getAllApps({ idsOnly: true, efficient: true })
+ }
- let apps = []
- if (!env.MULTI_TENANCY || tenantId) {
- // Apps exist
- apps = await getAllApps({ idsOnly: true, efficient: true })
- }
+ // They have set up SMTP
+ const smtpConfig = await getScopedFullConfig(db, {
+ type: Configs.SMTP,
+ })
- // They have set up SMTP
- const smtpConfig = await getScopedFullConfig(db, {
- type: Configs.SMTP,
- })
+ // They have set up Google Auth
+ const googleConfig = await getScopedFullConfig(db, {
+ type: Configs.GOOGLE,
+ })
- // They have set up Google Auth
- const googleConfig = await getScopedFullConfig(db, {
- type: Configs.GOOGLE,
- })
+ // They have set up OIDC
+ const oidcConfig = await getScopedFullConfig(db, {
+ type: Configs.OIDC,
+ })
- // They have set up OIDC
- const oidcConfig = await getScopedFullConfig(db, {
- type: Configs.OIDC,
- })
- // They have set up an global user
- const users = await db.allDocs(
- getGlobalUserParams(null, {
- include_docs: true,
- })
+ // They have set up an global user
+ const users = await db.allDocs(
+ getGlobalUserParams(null, {
+ include_docs: true,
+ limit: 1,
+ })
+ )
+ return {
+ apps: {
+ checked: apps.length > 0,
+ label: "Create your first app",
+ link: "/builder/portal/apps",
+ },
+ smtp: {
+ checked: !!smtpConfig,
+ label: "Set up email",
+ link: "/builder/portal/manage/email",
+ },
+ adminUser: {
+ checked: users && users.rows.length >= 1,
+ label: "Create your first user",
+ link: "/builder/portal/manage/users",
+ },
+ sso: {
+ checked: !!googleConfig || !!oidcConfig,
+ label: "Set up single sign-on",
+ link: "/builder/portal/manage/auth",
+ },
+ }
+ }
)
- const adminUser = users.rows.some(row => row.doc.admin)
-
- ctx.body = {
- apps: {
- checked: apps.length > 0,
- label: "Create your first app",
- link: "/builder/portal/apps",
- },
- smtp: {
- checked: !!smtpConfig,
- label: "Set up email",
- link: "/builder/portal/manage/email",
- },
- adminUser: {
- checked: adminUser,
- label: "Create your first user",
- link: "/builder/portal/manage/users",
- },
- sso: {
- checked: !!googleConfig || !!oidcConfig,
- label: "Set up single sign-on",
- link: "/builder/portal/manage/auth",
- },
- }
} catch (err) {
ctx.throw(err.status, err)
}
diff --git a/packages/worker/src/api/controllers/global/users.ts b/packages/worker/src/api/controllers/global/users.ts
index 441a1f15ab..11cf03d0cc 100644
--- a/packages/worker/src/api/controllers/global/users.ts
+++ b/packages/worker/src/api/controllers/global/users.ts
@@ -3,9 +3,6 @@ const {
StaticDatabases,
} = require("@budibase/backend-core/db")
const { getGlobalUserByEmail } = require("@budibase/backend-core/utils")
-import { EmailTemplatePurpose } from "../../../constants"
-import { checkInviteCode } from "../../../utilities/redis"
-import { sendEmail } from "../../../utilities/email"
const { user: userCache } = require("@budibase/backend-core/cache")
const { invalidateSessions } = require("@budibase/backend-core/sessions")
const accounts = require("@budibase/backend-core/accounts")
@@ -17,11 +14,15 @@ const {
doesTenantExist,
} = require("@budibase/backend-core/tenancy")
const { removeUserFromInfoDB } = require("@budibase/backend-core/deprovision")
+const { errors } = require("@budibase/backend-core")
+const { CacheKeys, bustCache } = require("@budibase/backend-core/cache")
import env from "../../../environment"
import { syncUserInApps } from "../../../utilities/appService"
import { quotas, users } from "@budibase/pro"
-const { errors } = require("@budibase/backend-core")
import { allUsers, getUser } from "../../utilities"
+import { EmailTemplatePurpose } from "../../../constants"
+import { checkInviteCode } from "../../../utilities/redis"
+import { sendEmail } from "../../../utilities/email"
export const save = async (ctx: any) => {
try {
@@ -93,7 +94,14 @@ export const adminUser = async (ctx: any) => {
tenantId,
}
try {
- ctx.body = await users.save(user, tenantId, hashPassword, requirePassword)
+ const finalUser = await users.save(
+ user,
+ tenantId,
+ hashPassword,
+ requirePassword
+ )
+ await bustCache(CacheKeys.CHECKLIST)
+ ctx.body = finalUser
} catch (err: any) {
ctx.throw(err.status || 400, err)
}
diff --git a/packages/worker/src/environment.js b/packages/worker/src/environment.js
index 125617a7ab..4c3cab1cab 100644
--- a/packages/worker/src/environment.js
+++ b/packages/worker/src/environment.js
@@ -1,3 +1,5 @@
+const { join } = require("path")
+
function isDev() {
return process.env.NODE_ENV !== "production"
}
@@ -12,10 +14,18 @@ function isTest() {
let LOADED = false
if (!LOADED && isDev() && !isTest()) {
- require("dotenv").config()
+ require("dotenv").config({
+ path: join(__dirname, "..", ".env"),
+ })
LOADED = true
}
+function parseIntSafe(number) {
+ if (number) {
+ return parseInt(number)
+ }
+}
+
module.exports = {
// auth
MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
@@ -49,6 +59,8 @@ module.exports = {
SMTP_HOST: process.env.SMTP_HOST,
SMTP_PORT: process.env.SMTP_PORT,
SMTP_FROM_ADDRESS: process.env.SMTP_FROM_ADDRESS,
+ // other
+ CHECKLIST_CACHE_TTL: parseIntSafe(process.env.CHECKLIST_CACHE_TTL) || 3600,
_set(key, value) {
process.env[key] = value
module.exports[key] = value
diff --git a/packages/worker/src/utilities/redis.js b/packages/worker/src/utilities/redis.js
index cfed97cd18..97adafa195 100644
--- a/packages/worker/src/utilities/redis.js
+++ b/packages/worker/src/utilities/redis.js
@@ -61,6 +61,7 @@ exports.shutdown = async () => {
* Given a user ID this will store a code (that is returned) for an hour in redis.
* The user can then return this code for resetting their password (through their reset link).
* @param {string} userId the ID of the user which is to be reset.
+ * @param {object} info Info about the user/the reset process.
* @return {Promise} returns the code that was stored to redis.
*/
exports.getResetPasswordCode = async (userId, info) => {
diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock
index e80de44f7c..dac5334edc 100644
--- a/packages/worker/yarn.lock
+++ b/packages/worker/yarn.lock
@@ -293,10 +293,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-"@budibase/backend-core@1.0.167-alpha.8":
- version "1.0.167-alpha.8"
- resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.167-alpha.8.tgz#e663928587cb3ec90d06b3c5766fce61c11e93a6"
- integrity sha512-J4LtucuaJJd5lAs9mV6Rt9D5dCZhKNrrKajnFTXqOrjsyw0jsIfN2ku8ClV0C9J3NA3wAu2zjpfDaKSnNfg2OQ==
+"@budibase/backend-core@1.0.176-alpha.0":
+ version "1.0.176-alpha.0"
+ resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.176-alpha.0.tgz#eca4d405f6a3feadc231ce851323005762b83b88"
+ integrity sha512-7GFAO499/rX/066jpChEH2CwOo+UI88MrZcceWqfbv3hBcV4nDUtVFUtzG63z74vQb9SHi0B15/qOYB5mzVQLw==
dependencies:
"@techpass/passport-openidconnect" "^0.3.0"
aws-sdk "^2.901.0"
@@ -322,12 +322,12 @@
uuid "^8.3.2"
zlib "^1.0.5"
-"@budibase/pro@1.0.167-alpha.8":
- version "1.0.167-alpha.8"
- resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.167-alpha.8.tgz#dfcecb85550bc07a89b8e0bd2dbff13543d99117"
- integrity sha512-MPEtYLnHfFchBzQs5nZSAavCANh32hd1VSXUB5KJSkEdtpQ9eoJ+hOGThrM9PJtTVX3Jq31nsg0/PmUkswBdAQ==
+"@budibase/pro@1.0.176-alpha.0":
+ version "1.0.176-alpha.0"
+ resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.176-alpha.0.tgz#416522800ef47b6ccc9e8bfc0e8d722db54f5c68"
+ integrity sha512-oe/HQsDpGZ3HO7t0TPqfKfh/FjZw5f9V22LxS45WXoOgL8b66U2WGwCaN7iF/zzxgPXlZ3h8TSHo9ai9d2UOgA==
dependencies:
- "@budibase/backend-core" "1.0.167-alpha.8"
+ "@budibase/backend-core" "1.0.176-alpha.0"
node-fetch "^2.6.1"
"@cspotcode/source-map-consumer@0.8.0":