mirror of https://github.com/Budibase/budibase.git
committed by
GitHub
18 changed files with 176 additions and 57 deletions
@ -0,0 +1,75 @@ |
|||||
|
const { APP_DEV_PREFIX } = require("../db/utils") |
||||
|
const { |
||||
|
doesUserHaveLock, |
||||
|
updateLock, |
||||
|
checkDebounce, |
||||
|
setDebounce, |
||||
|
} = require("../utilities/redis") |
||||
|
const CouchDB = require("../db") |
||||
|
const { DocumentTypes } = require("../db/utils") |
||||
|
const { PermissionTypes } = require("@budibase/auth/permissions") |
||||
|
|
||||
|
const DEBOUNCE_TIME_SEC = 30 |
||||
|
|
||||
|
/************************************************** * |
||||
|
* This middleware has been broken out of the * |
||||
|
* "authorized" middleware as it had nothing to do * |
||||
|
* with authorization, but requires the perms * |
||||
|
* imparted by it. This middleware shouldn't * |
||||
|
* be called directly, it should always be called * |
||||
|
* through the authorized middleware * |
||||
|
****************************************************/ |
||||
|
|
||||
|
async function checkDevAppLocks(ctx) { |
||||
|
const appId = ctx.appId |
||||
|
|
||||
|
// if any public usage, don't proceed
|
||||
|
if (!ctx.user._id && !ctx.user.userId) { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
// not a development app, don't need to do anything
|
||||
|
if (!appId || !appId.startsWith(APP_DEV_PREFIX)) { |
||||
|
return |
||||
|
} |
||||
|
if (!(await doesUserHaveLock(appId, ctx.user))) { |
||||
|
ctx.throw(403, "User does not hold app lock.") |
||||
|
} |
||||
|
|
||||
|
// they do have lock, update it
|
||||
|
await updateLock(appId, ctx.user) |
||||
|
} |
||||
|
|
||||
|
async function updateAppUpdatedAt(ctx) { |
||||
|
const appId = ctx.appId |
||||
|
// if debouncing skip this update
|
||||
|
// get methods also aren't updating
|
||||
|
if (ctx.method === "GET" || (await checkDebounce(appId))) { |
||||
|
return |
||||
|
} |
||||
|
const db = new CouchDB(appId) |
||||
|
const metadata = await db.get(DocumentTypes.APP_METADATA) |
||||
|
metadata.updatedAt = new Date().toISOString() |
||||
|
await db.put(metadata) |
||||
|
// set a new debounce record with a short TTL
|
||||
|
await setDebounce(appId, DEBOUNCE_TIME_SEC) |
||||
|
} |
||||
|
|
||||
|
module.exports = async (ctx, permType) => { |
||||
|
const appId = ctx.appId |
||||
|
// this only functions within an app context
|
||||
|
if (!appId) { |
||||
|
return |
||||
|
} |
||||
|
const isBuilderApi = permType === PermissionTypes.BUILDER |
||||
|
const referer = ctx.headers["referer"] |
||||
|
const editingApp = referer ? referer.includes(appId) : false |
||||
|
// check this is a builder call and editing
|
||||
|
if (!isBuilderApi || !editingApp) { |
||||
|
return |
||||
|
} |
||||
|
// check locks
|
||||
|
await checkDevAppLocks(ctx) |
||||
|
// set updated at time on app
|
||||
|
await updateAppUpdatedAt(ctx) |
||||
|
} |
||||
Loading…
Reference in new issue