From 1b54845c5e1da2fbecab5932acd995a5c15f2f70 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 20 Apr 2021 18:14:36 +0100 Subject: [PATCH] config creation and management APIs --- packages/auth/src/db/utils.js | 26 +++++++- packages/auth/src/index.js | 4 ++ .../auth/src/middleware/passport/google.js | 14 +++-- .../src/api/controllers/admin/configs.js | 60 +++++++++++++++++++ .../worker/src/api/routes/admin/configs.js | 28 +++++++++ packages/worker/src/api/routes/index.js | 3 +- packages/worker/src/constants/index.js | 6 ++ 7 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 packages/worker/src/api/controllers/admin/configs.js create mode 100644 packages/worker/src/api/routes/admin/configs.js diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 89aedb60bf..32034bd731 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -10,6 +10,7 @@ const DocumentTypes = { USER: "us", APP: "app", GROUP: "group", + CONFIG: "config", } exports.DocumentTypes = DocumentTypes @@ -52,7 +53,7 @@ exports.getGroupParams = (id = "", otherProps = {}) => { } /** - * Gets parameters for retrieving users. + * Gets parameters for retrieving users, this is a utility function for the getDocParams function. */ exports.getUserParams = (email = "", otherProps = {}) => { if (!email) { @@ -64,3 +65,26 @@ exports.getUserParams = (email = "", otherProps = {}) => { endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`, } } + +/** + * Generates a new configuration ID. + * @returns {string} The new configuration ID which the config doc can be stored under. + */ +exports.generateConfigID = (type = "", group = "") => { + group += SEPARATOR + + return `${ + DocumentTypes.CONFIG + }${SEPARATOR}${type}${SEPARATOR}${group}${newid()}` +} + +/** + * Gets parameters for retrieving configurations. + */ +exports.getConfigParams = (type = "", group = "", otherProps = {}) => { + return { + ...otherProps, + startkey: `${DocumentTypes.CONFIG}${SEPARATOR}${type}${SEPARATOR}${group}`, + endkey: `${DocumentTypes.CONFIG}${SEPARATOR}${type}${SEPARATOR}${group}${UNICODE_MAX}`, + } +} diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 455181d538..4c6ece1b62 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -20,6 +20,8 @@ const { generateGroupID, getGroupParams, getEmailFromUserID, + generateConfigID, + getConfigParams, } = require("./db/utils") // Strategies @@ -54,6 +56,8 @@ module.exports = { generateGroupID, getGroupParams, getEmailFromUserID, + generateConfigID, + getConfigParams, hash, compare, getAppId, diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index 05b435aedd..6246e5e768 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -6,7 +6,13 @@ exports.options = { callbackURL: env.GOOGLE_AUTH_CALLBACK_URL, } -// exports.authenticate = async function(token, tokenSecret, profile, done) { -// // retrieve user ... -// fetchUser().then(user => done(null, user)) -// } +exports.authenticate = async function(token, tokenSecret, profile, done) { + console.log({ + token, + tokenSecret, + profile, + done, + }) + // retrieve user ... + // fetchUser().then(user => done(null, user)) +} diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js new file mode 100644 index 0000000000..e9fc8a3942 --- /dev/null +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -0,0 +1,60 @@ +const CouchDB = require("../../../db") +const { StaticDatabases } = require("@budibase/auth") +const { generateConfigID } = require("@budibase/auth") +const { getConfigParams } = require("@budibase/auth/src/db/utils") + +const GLOBAL_DB = StaticDatabases.GLOBAL.name + +exports.save = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + const configDoc = ctx.request.body + + // Config does not exist yet + if (!configDoc._id) { + configDoc._id = generateConfigID(configDoc.type, configDoc.group) + } + + try { + const response = await db.post(configDoc) + ctx.body = { + type: configDoc.type, + _id: response.id, + _rev: response.rev, + } + } catch (err) { + ctx.throw(err.status, err) + } +} + +exports.fetch = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + const response = await db.allDocs( + getConfigParams(undefined, { + include_docs: true, + }) + ) + const groups = response.rows.map(row => row.doc) + ctx.body = groups +} + +exports.find = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + try { + const record = await db.get(ctx.params.id) + ctx.body = record + } catch (err) { + ctx.throw(err.status, err) + } +} + +exports.destroy = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + const { id, rev } = ctx.params + + try { + await db.remove(id, rev) + ctx.body = { message: "Config deleted successfully" } + } catch (err) { + ctx.throw(err.status, err) + } +} diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js new file mode 100644 index 0000000000..5b7354bfc3 --- /dev/null +++ b/packages/worker/src/api/routes/admin/configs.js @@ -0,0 +1,28 @@ +const Router = require("@koa/router") +const controller = require("../../controllers/admin/configs") +const joiValidator = require("../../../middleware/joi-validator") +const { authenticated } = require("@budibase/auth") +const Joi = require("joi") +const { Configs } = require("../../../constants") + +const router = Router() + +function buildConfigSaveValidation() { + // prettier-ignore + return joiValidator.body(Joi.object({ + type: Joi.string().valid(...Object.values(Configs)).required() + }).required().unknown(true)) +} + +router + .post( + "/api/admin/configs", + buildConfigSaveValidation(), + authenticated, + controller.save + ) + .delete("/api/admin/configs/:id", authenticated, controller.destroy) + .get("/api/admin/configs", authenticated, controller.fetch) + .get("/api/admin/configs/:id", authenticated, controller.find) + +module.exports = router diff --git a/packages/worker/src/api/routes/index.js b/packages/worker/src/api/routes/index.js index 5c6b088443..aa1c6874e3 100644 --- a/packages/worker/src/api/routes/index.js +++ b/packages/worker/src/api/routes/index.js @@ -1,6 +1,7 @@ const userRoutes = require("./admin/users") +const configRoutes = require("./admin/configs") const groupRoutes = require("./admin/groups") const authRoutes = require("./auth") const appRoutes = require("./app") -exports.routes = [userRoutes, groupRoutes, authRoutes, appRoutes] +exports.routes = [configRoutes, userRoutes, groupRoutes, authRoutes, appRoutes] diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 586d69c86f..76245a3d7d 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -6,3 +6,9 @@ exports.UserStatus = { exports.Groups = { ALL_USERS: "all_users", } + +exports.Configs = { + SETTINGS: "settings", + ACCOUNT: "account", + SMTP: "smtp", +}