From 7170c00a4f428a0e237aa3455da90323c616e7d1 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 16 Nov 2021 20:56:24 +0000 Subject: [PATCH] Fix for cypress test issues, when metadata is updated rapidly it could get into a bad state - this should resolve it. --- packages/auth/src/cache/appMetadata.js | 14 +++++++++++++- packages/auth/src/middleware/authenticated.js | 4 ++++ packages/server/scripts/likeCypress.ts | 14 +++++++------- packages/server/src/api/controllers/application.js | 1 + packages/server/src/api/controllers/dev.js | 3 ++- packages/server/src/middleware/builder.js | 5 +++-- 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/packages/auth/src/cache/appMetadata.js b/packages/auth/src/cache/appMetadata.js index 982f95dbe5..9e2317ae37 100644 --- a/packages/auth/src/cache/appMetadata.js +++ b/packages/auth/src/cache/appMetadata.js @@ -67,7 +67,19 @@ exports.getAppMetadata = async (appId, CouchDB = null) => { return metadata } -exports.invalidateAppMetadata = async appId => { +/** + * Invalidate/reset the cached metadata when a change occurs in the db. + * @param appId {string} the cache key to bust/update. + * @param newMetadata {object|undefined} optional - can simply provide the new metadata to update with. + * @return {Promise} will respond with success when cache is updated. + */ +exports.invalidateAppMetadata = async (appId, newMetadata = null) => { + if (!appId) { + throw "Cannot invalidate if no app ID provided." + } const client = await redis.getAppClient() await client.delete(appId) + if (newMetadata) { + await client.store(appId, newMetadata, EXPIRY_SECONDS) + } } diff --git a/packages/auth/src/middleware/authenticated.js b/packages/auth/src/middleware/authenticated.js index 4223e7e395..f0fb6e21c5 100644 --- a/packages/auth/src/middleware/authenticated.js +++ b/packages/auth/src/middleware/authenticated.js @@ -92,6 +92,10 @@ module.exports = ( finalise(ctx, { authenticated, user, internal, version, publicEndpoint }) return next() } catch (err) { + // invalid token, clear the cookie + if (err && err.name === "JsonWebTokenError") { + clearCookie(ctx, Cookies.Auth) + } // allow configuring for public access if ((opts && opts.publicAllowed) || publicEndpoint) { finalise(ctx, { authenticated: false, version, publicEndpoint }) diff --git a/packages/server/scripts/likeCypress.ts b/packages/server/scripts/likeCypress.ts index 505dbef523..625b4386e1 100644 --- a/packages/server/scripts/likeCypress.ts +++ b/packages/server/scripts/likeCypress.ts @@ -5,19 +5,19 @@ const path = require("path") const tmpdir = path.join(require("os").tmpdir(), ".budibase") -const MAIN_PORT = "4002" -const WORKER_PORT = "4001" +const MAIN_PORT = "10001" +const WORKER_PORT = "10002" // @ts-ignore -process.env.PORT = "4001" +process.env.PORT = MAIN_PORT process.env.BUDIBASE_API_KEY = "6BE826CB-6B30-4AEC-8777-2E90464633DE" process.env.NODE_ENV = "cypress" process.env.ENABLE_ANALYTICS = "false" process.env.JWT_SECRET = "budibase" process.env.COUCH_URL = `leveldb://${tmpdir}/.data/` process.env.SELF_HOSTED = "1" -process.env.WORKER_URL = "http://localhost:4002/" -process.env.MINIO_URL = `http://localhost:4001/` +process.env.WORKER_URL = `http://localhost:${WORKER_PORT}/` +process.env.MINIO_URL = `http://localhost:${MAIN_PORT}/` process.env.MINIO_ACCESS_KEY = "budibase" process.env.MINIO_SECRET_KEY = "budibase" process.env.COUCH_DB_USER = "budibase" @@ -28,6 +28,6 @@ process.env.ALLOW_DEV_AUTOMATIONS = "1" // don't make this a variable or top level require // it will cause environment module to be loaded prematurely const server = require("../src/app") -process.env.PORT = "4002" +process.env.PORT = WORKER_PORT const worker = require("../../worker/src/index") -process.env.PORT = "4001" \ No newline at end of file +process.env.PORT = MAIN_PORT \ No newline at end of file diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index d38312af2f..cd14313b47 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -255,6 +255,7 @@ exports.create = async ctx => { await createApp(appId) } + await appCache.invalidateAppMetadata(appId, newApplication) ctx.status = 200 ctx.body = newApplication } diff --git a/packages/server/src/api/controllers/dev.js b/packages/server/src/api/controllers/dev.js index dbea82b06b..559ffcbcfd 100644 --- a/packages/server/src/api/controllers/dev.js +++ b/packages/server/src/api/controllers/dev.js @@ -25,7 +25,8 @@ async function redirect(ctx, method, path = "global") { ) ) if (response.status !== 200) { - ctx.throw(response.status, response.statusText) + const err = await response.text() + ctx.throw(400, err) } const cookie = response.headers.get("set-cookie") if (cookie) { diff --git a/packages/server/src/middleware/builder.js b/packages/server/src/middleware/builder.js index 427e54287a..f8a84c4c25 100644 --- a/packages/server/src/middleware/builder.js +++ b/packages/server/src/middleware/builder.js @@ -51,8 +51,9 @@ async function updateAppUpdatedAt(ctx) { const db = new CouchDB(appId) const metadata = await db.get(DocumentTypes.APP_METADATA) metadata.updatedAt = new Date().toISOString() - await db.put(metadata) - await appCache.invalidateAppMetadata(appId) + const response = await db.put(metadata) + metadata._rev = response.rev + await appCache.invalidateAppMetadata(appId, metadata) // set a new debounce record with a short TTL await setDebounce(appId, DEBOUNCE_TIME_SEC) }