Updating locks to store the whole global user as well as implementing the locks on dev apps fetch.

This commit is contained in:
mike12345567 2021-05-13 12:16:09 +01:00
parent 61a5b109f5
commit 799b3fc138
4 changed files with 48 additions and 21 deletions

View File

@ -35,6 +35,7 @@ const { getAllApps } = require("../../utilities")
const { USERS_TABLE_SCHEMA } = require("../../constants") const { USERS_TABLE_SCHEMA } = require("../../constants")
const { getDeployedApps } = require("../../utilities/workerRequests") const { getDeployedApps } = require("../../utilities/workerRequests")
const { clientLibraryPath } = require("../../utilities") const { clientLibraryPath } = require("../../utilities")
const { getAllLocks } = require("../../utilities/redis")
const URL_REGEX_SLASH = /\/|\\/g const URL_REGEX_SLASH = /\/|\\/g
@ -122,15 +123,23 @@ async function createInstance(template) {
exports.fetch = async function (ctx) { exports.fetch = async function (ctx) {
let apps = await getAllApps() let apps = await getAllApps()
const appStatus = ctx.query.status const isDev = ctx.query.status === AppStatus.DEV
if (appStatus) {
apps = apps.filter(app => { apps = apps.filter(app => {
if (appStatus === AppStatus.DEV) { if (isDev) {
return app._id.startsWith(DocumentTypes.APP_DEV) return app._id.startsWith(DocumentTypes.APP_DEV)
} }
return !app._id.startsWith(DocumentTypes.APP_DEV) return !app._id.startsWith(DocumentTypes.APP_DEV)
}) })
// get the locks for all the dev apps
if (isDev) {
const locks = await getAllLocks()
for (let app of apps) {
const lock = locks.find(lock => lock.appId === app._id)
if (lock) {
app.lockedBy = lock.user
}
}
} }
ctx.body = apps ctx.body = apps

View File

@ -37,9 +37,8 @@ exports.redirectDelete = async ctx => {
exports.removeLock = async ctx => { exports.removeLock = async ctx => {
const { appId } = ctx.params const { appId } = ctx.params
const globalUserId = getGlobalIDFromUserMetadataID(ctx.user._id)
try { try {
await clearLock(appId, globalUserId) await clearLock(appId, ctx.user)
} catch (err) { } catch (err) {
ctx.throw(400, "Unable to remove lock.") ctx.throw(400, "Unable to remove lock.")
} }

View File

@ -4,7 +4,7 @@ const {
doesHaveResourcePermission, doesHaveResourcePermission,
doesHaveBasePermission, doesHaveBasePermission,
} = require("../utilities/security/permissions") } = require("../utilities/security/permissions")
const { APP_DEV_PREFIX, getGlobalIDFromUserMetadataID } = require("../db/utils") const { APP_DEV_PREFIX } = require("../db/utils")
const { doesUserHaveLock, updateLock } = require("../utilities/redis") const { doesUserHaveLock, updateLock } = require("../utilities/redis")
function hasResource(ctx) { function hasResource(ctx) {
@ -19,17 +19,15 @@ async function checkDevAppLocks(ctx) {
const appId = ctx.appId const appId = ctx.appId
// not a development app, don't need to do anything // not a development app, don't need to do anything
if (!appId.startsWith(APP_DEV_PREFIX)) { if (!appId || !appId.startsWith(APP_DEV_PREFIX)) {
return return
} }
// get the user which is currently using the dev app if (!(await doesUserHaveLock(appId, ctx.user))) {
const userId = getGlobalIDFromUserMetadataID(ctx.user._id)
if (!(await doesUserHaveLock(appId, userId))) {
ctx.throw(403, "User does not hold app lock.") ctx.throw(403, "User does not hold app lock.")
} }
// they do have lock, update it // they do have lock, update it
await updateLock(appId, userId) await updateLock(appId, ctx.user)
} }
module.exports = (permType, permLevel = null) => async (ctx, next) => { module.exports = (permType, permLevel = null) => async (ctx, next) => {

View File

@ -1,4 +1,5 @@
const { Client, utils } = require("@budibase/auth").redis const { Client, utils } = require("@budibase/auth").redis
const { getGlobalIDFromUserMetadataID } = require("../db/utils")
const APP_DEV_LOCK_SECONDS = 600 const APP_DEV_LOCK_SECONDS = 600
const DB_NAME = utils.Databases.DEV_LOCKS const DB_NAME = utils.Databases.DEV_LOCKS
@ -10,20 +11,40 @@ exports.init = async () => {
devAppClient = await new Client(DB_NAME).init() devAppClient = await new Client(DB_NAME).init()
} }
exports.doesUserHaveLock = async (devAppId, userId) => { exports.doesUserHaveLock = async (devAppId, user) => {
const value = await devAppClient.get(devAppId) const value = await devAppClient.get(devAppId)
return value == null || value === userId if (!value) {
return true
}
// make sure both IDs are global
const expected = getGlobalIDFromUserMetadataID(value._id)
const userId = getGlobalIDFromUserMetadataID(user._id)
return expected === userId
} }
exports.updateLock = async (devAppId, userId) => { exports.getAllLocks = async () => {
await devAppClient.store(devAppId, userId, APP_DEV_LOCK_SECONDS) const locks = await devAppClient.scan()
return locks.map(lock => ({
appId: lock.key,
user: lock.value,
}))
} }
exports.clearLock = async (devAppId, userId) => { exports.updateLock = async (devAppId, user) => {
// make sure always global user ID
const inputUser = {
...user,
_id: getGlobalIDFromUserMetadataID(user._id),
}
await devAppClient.store(devAppId, inputUser, APP_DEV_LOCK_SECONDS)
}
exports.clearLock = async (devAppId, user) => {
const value = await devAppClient.get(devAppId) const value = await devAppClient.get(devAppId)
if (!value) { if (!value) {
return return
} }
const userId = getGlobalIDFromUserMetadataID(user._id)
if (value !== userId) { if (value !== userId) {
throw "User does not hold lock, cannot clear it." throw "User does not hold lock, cannot clear it."
} }