budibase/packages/server/src/middleware/authorized.js

88 lines
2.0 KiB
JavaScript
Raw Normal View History

2020-05-27 18:23:01 +02:00
const {
adminPermissions,
ADMIN_LEVEL_ID,
POWERUSER_LEVEL_ID,
2020-06-18 17:59:31 +02:00
BUILDER_LEVEL_ID,
2020-05-27 18:23:01 +02:00
BUILDER,
} = require("../utilities/accessLevels")
const env = require("../environment")
2020-10-12 12:57:37 +02:00
const { apiKeyTable } = require("../db/dynamoClient")
const { AuthTypes } = require("../constants")
2020-05-27 18:23:01 +02:00
const LOCAL_PASS = new RegExp(["webhooks/trigger", "webhooks/schema"].join("|"))
2020-05-27 18:23:01 +02:00
module.exports = (permName, getItemId) => async (ctx, next) => {
// webhooks can pass locally
if (!env.CLOUD && LOCAL_PASS.test(ctx.request.url)) {
return next()
}
if (env.CLOUD && ctx.headers["x-api-key"] && ctx.headers["x-instanceid"]) {
2020-10-12 12:57:37 +02:00
// api key header passed by external webhook
const apiKeyInfo = await apiKeyTable.get({
primary: ctx.headers["x-api-key"],
})
if (apiKeyInfo) {
ctx.auth = {
authenticated: AuthTypes.EXTERNAL,
apiKey: ctx.headers["x-api-key"],
}
2020-10-12 12:57:37 +02:00
ctx.user = {
appId: ctx.headers["x-instanceid"],
2020-10-12 12:57:37 +02:00
}
return next()
}
ctx.throw(403, "API key invalid")
}
// don't expose builder endpoints in the cloud
if (env.CLOUD && permName === BUILDER) return
if (!ctx.auth.authenticated) {
2020-05-27 18:23:01 +02:00
ctx.throw(403, "Session not authenticated")
}
2020-06-18 17:59:31 +02:00
if (!ctx.user) {
ctx.throw(403, "User not found")
}
if (ctx.user.accessLevel._id === ADMIN_LEVEL_ID) {
return next()
}
2020-06-18 17:59:31 +02:00
if (ctx.user.accessLevel._id === BUILDER_LEVEL_ID) {
return next()
2020-05-27 18:23:01 +02:00
}
if (permName === BUILDER) {
ctx.throw(403, "Not Authorized")
return
}
const permissionId = ({ name, itemId }) => name + (itemId ? `-${itemId}` : "")
const thisPermissionId = permissionId({
name: permName,
itemId: getItemId && getItemId(ctx),
})
// power user has everything, except the admin specific perms
if (
ctx.user.accessLevel._id === POWERUSER_LEVEL_ID &&
!adminPermissions.map(permissionId).includes(thisPermissionId)
) {
return next()
2020-05-27 18:23:01 +02:00
}
if (
ctx.user.accessLevel.permissions
.map(permissionId)
.includes(thisPermissionId)
) {
return next()
2020-05-27 18:23:01 +02:00
}
ctx.throw(403, "Not Authorized")
}