diff --git a/packages/backend-core/src/auth.js b/packages/backend-core/src/auth.js index b60144a0de..9ae29a3cbd 100644 --- a/packages/backend-core/src/auth.js +++ b/packages/backend-core/src/auth.js @@ -18,6 +18,8 @@ const { ssoCallbackUrl, csrf, internalApi, + adminOnly, + joiValidator, } = require("./middleware") const { invalidateUser } = require("./cache/user") @@ -173,4 +175,6 @@ module.exports = { refreshOAuthToken, updateUserOAuth, ssoCallbackUrl, + adminOnly, + joiValidator, } diff --git a/packages/backend-core/src/middleware/adminOnly.js b/packages/backend-core/src/middleware/adminOnly.js new file mode 100644 index 0000000000..4bfdf83848 --- /dev/null +++ b/packages/backend-core/src/middleware/adminOnly.js @@ -0,0 +1,9 @@ +module.exports = async (ctx, next) => { + if ( + !ctx.internal && + (!ctx.user || !ctx.user.admin || !ctx.user.admin.global) + ) { + ctx.throw(403, "Admin user only endpoint.") + } + return next() +} diff --git a/packages/backend-core/src/middleware/index.js b/packages/backend-core/src/middleware/index.js index 1721d56a3c..9d94bf5763 100644 --- a/packages/backend-core/src/middleware/index.js +++ b/packages/backend-core/src/middleware/index.js @@ -9,7 +9,8 @@ const tenancy = require("./tenancy") const internalApi = require("./internalApi") const datasourceGoogle = require("./passport/datasource/google") const csrf = require("./csrf") - +const adminOnly = require("./adminOnly") +const joiValidator = require("./joi-validator") module.exports = { google, oidc, @@ -25,4 +26,6 @@ module.exports = { google: datasourceGoogle, }, csrf, + adminOnly, + joiValidator, } diff --git a/packages/backend-core/src/middleware/joi-validator.js b/packages/backend-core/src/middleware/joi-validator.js new file mode 100644 index 0000000000..1686b0e727 --- /dev/null +++ b/packages/backend-core/src/middleware/joi-validator.js @@ -0,0 +1,28 @@ +function validate(schema, property) { + // Return a Koa middleware function + return (ctx, next) => { + if (!schema) { + return next() + } + let params = null + if (ctx[property] != null) { + params = ctx[property] + } else if (ctx.request[property] != null) { + params = ctx.request[property] + } + const { error } = schema.validate(params) + if (error) { + ctx.throw(400, `Invalid ${property} - ${error.message}`) + return + } + return next() + } +} + +module.exports.body = schema => { + return validate(schema, "body") +} + +module.exports.params = schema => { + return validate(schema, "params") +} diff --git a/packages/server/src/api/controllers/query/validation.js b/packages/server/src/api/controllers/query/validation.js index 2b5a3b310d..c390146001 100644 --- a/packages/server/src/api/controllers/query/validation.js +++ b/packages/server/src/api/controllers/query/validation.js @@ -1,4 +1,4 @@ -const joiValidator = require("../../../middleware/joi-validator") +const { joiValidator } = require("@budibase/backend-core/auth") const Joi = require("joi") const OPTIONAL_STRING = Joi.string().optional().allow(null).allow("") diff --git a/packages/server/src/api/routes/utils/validators.js b/packages/server/src/api/routes/utils/validators.js index 1a094e380b..b43eea9e36 100644 --- a/packages/server/src/api/routes/utils/validators.js +++ b/packages/server/src/api/routes/utils/validators.js @@ -1,4 +1,4 @@ -const joiValidator = require("../../../middleware/joi-validator") +const { joiValidator } = require("@budibase/backend-core/auth") const { DataSourceOperation } = require("../../../constants") const { WebhookType } = require("../../../constants") const { diff --git a/packages/worker/src/api/routes/global/auth.js b/packages/worker/src/api/routes/global/auth.js index cc00b4f82f..07d95f808d 100644 --- a/packages/worker/src/api/routes/global/auth.js +++ b/packages/worker/src/api/routes/global/auth.js @@ -1,6 +1,6 @@ const Router = require("@koa/router") const authController = require("../../controllers/global/auth") -const joiValidator = require("../../../middleware/joi-validator") +const { joiValidator } = require("@budibase/backend-core/auth") const Joi = require("joi") const { updateTenantId } = require("@budibase/backend-core/tenancy") diff --git a/packages/worker/src/api/routes/global/configs.js b/packages/worker/src/api/routes/global/configs.js index 174e68b2f9..c4beb57600 100644 --- a/packages/worker/src/api/routes/global/configs.js +++ b/packages/worker/src/api/routes/global/configs.js @@ -1,7 +1,7 @@ const Router = require("@koa/router") const controller = require("../../controllers/global/configs") -const joiValidator = require("../../../middleware/joi-validator") -const adminOnly = require("../../../middleware/adminOnly") +const { joiValidator } = require("@budibase/backend-core/auth") +const { adminOnly } = require("@budibase/backend-core/auth") const Joi = require("joi") const { Configs } = require("../../../constants") @@ -77,7 +77,7 @@ function buildConfigSaveValidation() { { is: Configs.OIDC, then: oidcValidation() } ], }), - }).required().unknown(true), + }).required().unknown(true), ) } diff --git a/packages/worker/src/api/routes/global/email.js b/packages/worker/src/api/routes/global/email.js index fecbc02cd7..b771728a0f 100644 --- a/packages/worker/src/api/routes/global/email.js +++ b/packages/worker/src/api/routes/global/email.js @@ -1,8 +1,8 @@ const Router = require("@koa/router") const controller = require("../../controllers/global/email") const { EmailTemplatePurpose } = require("../../../constants") -const joiValidator = require("../../../middleware/joi-validator") -const adminOnly = require("../../../middleware/adminOnly") +const { joiValidator } = require("@budibase/backend-core/auth") +const { adminOnly } = require("@budibase/backend-core/auth") const Joi = require("joi") const router = Router() diff --git a/packages/worker/src/api/routes/global/roles.js b/packages/worker/src/api/routes/global/roles.js index ab79883ab8..4e27b7d54b 100644 --- a/packages/worker/src/api/routes/global/roles.js +++ b/packages/worker/src/api/routes/global/roles.js @@ -1,6 +1,6 @@ const Router = require("@koa/router") const controller = require("../../controllers/global/roles") -const adminOnly = require("../../../middleware/adminOnly") +const { adminOnly } = require("@budibase/backend-core/auth") const router = Router() diff --git a/packages/worker/src/api/routes/global/sessions.js b/packages/worker/src/api/routes/global/sessions.js index 5ba6747e68..6ab4ad8e59 100644 --- a/packages/worker/src/api/routes/global/sessions.js +++ b/packages/worker/src/api/routes/global/sessions.js @@ -1,6 +1,6 @@ const Router = require("@koa/router") const controller = require("../../controllers/global/sessions") -const adminOnly = require("../../../middleware/adminOnly") +const { adminOnly } = require("@budibase/backend-core/auth") const router = Router() diff --git a/packages/worker/src/api/routes/global/templates.js b/packages/worker/src/api/routes/global/templates.js index e4580d444c..321e0543ad 100644 --- a/packages/worker/src/api/routes/global/templates.js +++ b/packages/worker/src/api/routes/global/templates.js @@ -1,9 +1,9 @@ const Router = require("@koa/router") const controller = require("../../controllers/global/templates") -const joiValidator = require("../../../middleware/joi-validator") +const { joiValidator } = require("@budibase/backend-core/auth") const Joi = require("joi") const { TemplatePurpose, TemplateTypes } = require("../../../constants") -const adminOnly = require("../../../middleware/adminOnly") +const { adminOnly } = require("@budibase/backend-core/auth") const router = Router() diff --git a/packages/worker/src/api/routes/global/users.js b/packages/worker/src/api/routes/global/users.js index 907ddd0f7b..daa1af034d 100644 --- a/packages/worker/src/api/routes/global/users.js +++ b/packages/worker/src/api/routes/global/users.js @@ -1,7 +1,7 @@ const Router = require("@koa/router") const controller = require("../../controllers/global/users") -const joiValidator = require("../../../middleware/joi-validator") -const adminOnly = require("../../../middleware/adminOnly") +const { joiValidator } = require("@budibase/backend-core/auth") +const { adminOnly } = require("@budibase/backend-core/auth") const Joi = require("joi") const cloudRestricted = require("../../../middleware/cloudRestricted") const { users } = require("../validation") diff --git a/packages/worker/src/api/routes/global/workspaces.js b/packages/worker/src/api/routes/global/workspaces.js index cab76b7763..0198991bfa 100644 --- a/packages/worker/src/api/routes/global/workspaces.js +++ b/packages/worker/src/api/routes/global/workspaces.js @@ -1,7 +1,7 @@ const Router = require("@koa/router") const controller = require("../../controllers/global/workspaces") -const joiValidator = require("../../../middleware/joi-validator") -const adminOnly = require("../../../middleware/adminOnly") +const { joiValidator } = require("@budibase/backend-core/auth") +const { adminOnly } = require("@budibase/backend-core/auth") const Joi = require("joi") const router = Router() @@ -17,9 +17,9 @@ function buildWorkspaceSaveValidation() { roles: Joi.object({ default: Joi.string().optional(), app: Joi.object() - .pattern(/.*/, Joi.string()) - .required() - .unknown(true), + .pattern(/.*/, Joi.string()) + .required() + .unknown(true), }).unknown(true).optional(), }).required().unknown(true)) } diff --git a/packages/worker/src/api/routes/system/tenants.js b/packages/worker/src/api/routes/system/tenants.js index 49c7509a67..451f09f773 100644 --- a/packages/worker/src/api/routes/system/tenants.js +++ b/packages/worker/src/api/routes/system/tenants.js @@ -1,6 +1,6 @@ const Router = require("@koa/router") const controller = require("../../controllers/system/tenants") -const adminOnly = require("../../../middleware/adminOnly") +const { adminOnly } = require("@budibase/backend-core/auth") const router = Router()