diff --git a/lerna.json b/lerna.json index f58bac059d..fd289506fa 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "1.0.173-alpha.0", + "version": "1.0.175", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 0e1251fbc1..26a4809f85 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "1.0.173-alpha.0", + "version": "1.0.175", "description": "Budibase backend core libraries used in server and worker", "main": "src/index.js", "author": "Budibase", 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/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/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/bbui/package.json b/packages/bbui/package.json index 60995d2cfd..e26a5dc113 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.173-alpha.0", + "version": "1.0.175", "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.173-alpha.0", + "@budibase/string-templates": "^1.0.175", "@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 07c530043f..e1404b7fa0 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "1.0.173-alpha.0", + "version": "1.0.175", "license": "GPL-3.0", "private": true, "scripts": { @@ -69,10 +69,10 @@ } }, "dependencies": { - "@budibase/bbui": "^1.0.173-alpha.0", - "@budibase/client": "^1.0.173-alpha.0", - "@budibase/frontend-core": "^1.0.173-alpha.0", - "@budibase/string-templates": "^1.0.173-alpha.0", + "@budibase/bbui": "^1.0.175", + "@budibase/client": "^1.0.175", + "@budibase/frontend-core": "^1.0.175", + "@budibase/string-templates": "^1.0.175", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/pages/builder/auth/login.svelte b/packages/builder/src/pages/builder/auth/login.svelte index 84af5b6338..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) { diff --git a/packages/cli/package.json b/packages/cli/package.json index eaaad65ec5..fb2e593c20 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "1.0.173-alpha.0", + "version": "1.0.175", "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 5d62184f80..6ea3f166c3 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "1.0.173-alpha.0", + "version": "1.0.175", "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.173-alpha.0", - "@budibase/frontend-core": "^1.0.173-alpha.0", - "@budibase/string-templates": "^1.0.173-alpha.0", + "@budibase/bbui": "^1.0.175", + "@budibase/frontend-core": "^1.0.175", + "@budibase/string-templates": "^1.0.175", "@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 43f89937af..e87e7f6e77 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -1,12 +1,12 @@ { "name": "@budibase/frontend-core", - "version": "1.0.173-alpha.0", + "version": "1.0.175", "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.173-alpha.0", + "@budibase/bbui": "^1.0.175", "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/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 9fa8671563..fd86e08780 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.173-alpha.0", + "version": "1.0.175", "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.173-alpha.0", - "@budibase/client": "^1.0.173-alpha.0", - "@budibase/pro": "1.0.173-alpha.0", - "@budibase/string-templates": "^1.0.173-alpha.0", + "@budibase/backend-core": "^1.0.175", + "@budibase/client": "^1.0.175", + "@budibase/pro": "1.0.175", + "@budibase/string-templates": "^1.0.175", "@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/yarn.lock b/packages/server/yarn.lock index 8a8cc1f660..41595a7715 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.3": - version "1.0.167-alpha.3" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.167-alpha.3.tgz#bb82ba4bbd6aaca47ceb97cb97047f4f615fd9a9" - integrity sha512-sETe50Nid+uuwg0/liEjhy9/o9ygjrYSOJJf1CzuC8xW1ni9wHMMrPx3vsHxYs21aE1+nW1hNgkCUw5kpw7Kjg== +"@budibase/backend-core@1.0.175": + version "1.0.175" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.175.tgz#9c8f71c00d3cde510c3b6843302700a9249969db" + integrity sha512-ZzIzNyiW6W8YPVTxsAQnaDEmVUtW22Bna8uJ9BEal/0u8JvYpvWnbPmpbrX7nadJ+5zIGJPxxpe97rhsHJeuaA== dependencies: "@techpass/passport-openidconnect" "^0.3.0" aws-sdk "^2.901.0" @@ -1091,12 +1091,12 @@ svelte-flatpickr "^3.2.3" svelte-portal "^1.0.0" -"@budibase/pro@1.0.167-alpha.3": - version "1.0.167-alpha.3" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.167-alpha.3.tgz#22fa274ffbd50e08dfe5ca4bb546f14d68ba02d4" - integrity sha512-y6bQmNxRRChGJUVRu/FEUdkBlYZlGpxMC8xBSd8oj1FDRdTofbL0it2XUEI3P8H5zBM0J33pw6x27dlWnrOItg== +"@budibase/pro@1.0.175": + version "1.0.175" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.175.tgz#1d8ddc698ad17e2f5d73b1ab741c6641da4bda47" + integrity sha512-iGqOtsXeO5bHcg4IJjg8NwOK5bNjI3TnJCr7PtcTjlLyZyCyj+onL2GTk3A6X+d1ZKSQKy9bl3Q+hIsdbZ9GIg== dependencies: - "@budibase/backend-core" "1.0.167-alpha.3" + "@budibase/backend-core" "1.0.175" 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 b9bc56833f..77916aca77 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "1.0.173-alpha.0", + "version": "1.0.175", "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 6b8a68dc26..5e0cd96397 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.173-alpha.0", + "version": "1.0.175", "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.173-alpha.0", - "@budibase/pro": "1.0.173-alpha.0", - "@budibase/string-templates": "^1.0.173-alpha.0", + "@budibase/backend-core": "^1.0.175", + "@budibase/pro": "1.0.175", + "@budibase/string-templates": "^1.0.175", "@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 147c5296ce..df3326ef26 100644 --- a/packages/worker/src/api/controllers/global/configs.js +++ b/packages/worker/src/api/controllers/global/configs.js @@ -17,7 +17,6 @@ const { googleCallbackUrl, oidcCallbackUrl } = require("./auth") const { withCache, CacheKeys, - TTL, bustCache, } = require("@budibase/backend-core/cache") @@ -256,58 +255,62 @@ exports.configChecklist = async function (ctx) { const tenantId = getTenantId() try { - ctx.body = await withCache(CacheKeys.CHECKLIST, TTL.ONE_HOUR, async () => { - let apps = [] - if (!env.MULTI_TENANCY || tenantId) { - // Apps exist - apps = await getAllApps({ idsOnly: true, efficient: true }) - } + 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 }) + } - // 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 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, - limit: 1, + // They have set up SMTP + const smtpConfig = await getScopedFullConfig(db, { + type: Configs.SMTP, }) - ) - 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", - }, + + // 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 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", + }, + } } - }) + ) } catch (err) { ctx.throw(err.status, err) } diff --git a/packages/worker/src/environment.js b/packages/worker/src/environment.js index 6f145aa6ac..4c3cab1cab 100644 --- a/packages/worker/src/environment.js +++ b/packages/worker/src/environment.js @@ -20,6 +20,12 @@ if (!LOADED && isDev() && !isTest()) { LOADED = true } +function parseIntSafe(number) { + if (number) { + return parseInt(number) + } +} + module.exports = { // auth MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, @@ -53,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/yarn.lock b/packages/worker/yarn.lock index 34530c0161..69af29dfa9 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.3": - version "1.0.167-alpha.3" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.167-alpha.3.tgz#bb82ba4bbd6aaca47ceb97cb97047f4f615fd9a9" - integrity sha512-sETe50Nid+uuwg0/liEjhy9/o9ygjrYSOJJf1CzuC8xW1ni9wHMMrPx3vsHxYs21aE1+nW1hNgkCUw5kpw7Kjg== +"@budibase/backend-core@1.0.175": + version "1.0.175" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.175.tgz#9c8f71c00d3cde510c3b6843302700a9249969db" + integrity sha512-ZzIzNyiW6W8YPVTxsAQnaDEmVUtW22Bna8uJ9BEal/0u8JvYpvWnbPmpbrX7nadJ+5zIGJPxxpe97rhsHJeuaA== dependencies: "@techpass/passport-openidconnect" "^0.3.0" aws-sdk "^2.901.0" @@ -321,12 +321,12 @@ uuid "^8.3.2" zlib "^1.0.5" -"@budibase/pro@1.0.167-alpha.3": - version "1.0.167-alpha.3" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.167-alpha.3.tgz#22fa274ffbd50e08dfe5ca4bb546f14d68ba02d4" - integrity sha512-y6bQmNxRRChGJUVRu/FEUdkBlYZlGpxMC8xBSd8oj1FDRdTofbL0it2XUEI3P8H5zBM0J33pw6x27dlWnrOItg== +"@budibase/pro@1.0.175": + version "1.0.175" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.175.tgz#1d8ddc698ad17e2f5d73b1ab741c6641da4bda47" + integrity sha512-iGqOtsXeO5bHcg4IJjg8NwOK5bNjI3TnJCr7PtcTjlLyZyCyj+onL2GTk3A6X+d1ZKSQKy9bl3Q+hIsdbZ9GIg== dependencies: - "@budibase/backend-core" "1.0.167-alpha.3" + "@budibase/backend-core" "1.0.175" node-fetch "^2.6.1" "@cspotcode/source-map-consumer@0.8.0":