From 2aff68b24598821d2582342534f6b2eec324fcdd Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 2 Oct 2020 12:37:46 +0100 Subject: [PATCH] Adding jsdoc to the db utils and removing the views, this is a breaking change for existing apps. --- .../server/src/api/controllers/accesslevel.js | 3 +- .../server/src/api/controllers/application.js | 3 +- .../server/src/api/controllers/automation.js | 3 +- packages/server/src/api/controllers/model.js | 3 +- packages/server/src/api/controllers/record.js | 3 +- packages/server/src/api/controllers/user.js | 18 +-- .../server/src/api/controllers/view/index.js | 17 +-- packages/server/src/automations/triggers.js | 11 +- packages/server/src/db/utils.js | 106 ++++++++++++++---- 9 files changed, 115 insertions(+), 52 deletions(-) diff --git a/packages/server/src/api/controllers/accesslevel.js b/packages/server/src/api/controllers/accesslevel.js index a607ed13c3..ab145a1b76 100644 --- a/packages/server/src/api/controllers/accesslevel.js +++ b/packages/server/src/api/controllers/accesslevel.js @@ -1,5 +1,4 @@ const CouchDB = require("../../db") -const newid = require("../../db/newid") const { generateAdminPermissions, generatePowerUserPermissions, @@ -95,7 +94,7 @@ exports.create = async function(ctx) { name: ctx.request.body.name, _rev: ctx.request.body._rev, permissions: ctx.request.body.permissions || [], - _id: generateAccessLevelID(newid()), + _id: generateAccessLevelID(), type: "accesslevel", } diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index b8d0d59344..ea8e348fa5 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -1,7 +1,6 @@ const CouchDB = require("../../db") const ClientDb = require("../../db/clientDb") const { getPackageForBuilder, buildPage } = require("../../utilities/builder") -const newid = require("../../db/newid") const env = require("../../environment") const instanceController = require("./instance") const { resolve, join } = require("path") @@ -49,7 +48,7 @@ exports.create = async function(ctx) { if (!clientId) { ctx.throw(400, "ClientId not suplied") } - const appId = generateAppID(newid()) + const appId = generateAppID() // insert an appId -> clientId lookup const masterDb = new CouchDB("client_app_lookup") diff --git a/packages/server/src/api/controllers/automation.js b/packages/server/src/api/controllers/automation.js index 81b5a6b87b..5414f3878c 100644 --- a/packages/server/src/api/controllers/automation.js +++ b/packages/server/src/api/controllers/automation.js @@ -1,5 +1,4 @@ const CouchDB = require("../../db") -const newid = require("../../db/newid") const actions = require("../../automations/actions") const logic = require("../../automations/logic") const triggers = require("../../automations/triggers") @@ -35,7 +34,7 @@ exports.create = async function(ctx) { const db = new CouchDB(ctx.user.instanceId) let automation = ctx.request.body - automation._id = generateAutomationID(newid()) + automation._id = generateAutomationID() automation.type = "automation" automation = cleanAutomationInputs(automation) diff --git a/packages/server/src/api/controllers/model.js b/packages/server/src/api/controllers/model.js index 59d2d66325..182b2089da 100644 --- a/packages/server/src/api/controllers/model.js +++ b/packages/server/src/api/controllers/model.js @@ -1,5 +1,4 @@ const CouchDB = require("../../db") -const newid = require("../../db/newid") const { getRecordParams, getModelParams, @@ -25,7 +24,7 @@ exports.save = async function(ctx) { const db = new CouchDB(ctx.user.instanceId) const modelToSave = { type: "model", - _id: generateModelID(newid()), + _id: generateModelID(), views: {}, ...ctx.request.body, } diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index 1344142d8e..7071070fc7 100644 --- a/packages/server/src/api/controllers/record.js +++ b/packages/server/src/api/controllers/record.js @@ -1,6 +1,5 @@ const CouchDB = require("../../db") const validateJs = require("validate.js") -const newid = require("../../db/newid") const { getRecordParams, generateRecordID } = require("../../db/utils") const MODEL_VIEW_BEGINS_WITH = "all_model:" @@ -69,7 +68,7 @@ exports.save = async function(ctx) { record.modelId = ctx.params.modelId if (!record._rev && !record._id) { - record._id = generateRecordID(record.modelId, newid()) + record._id = generateRecordID(record.modelId) } const model = await db.get(record.modelId) diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index 3933e4f790..4e749f0ff7 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -1,7 +1,7 @@ const CouchDB = require("../../db") const clientDb = require("../../db/clientDb") const bcrypt = require("../../utilities/bcrypt") -const getUserId = userName => `user_${userName}` +const { generateUserID, getUserParams } = require("../../db/utils") const { POWERUSER_LEVEL_ID, ADMIN_LEVEL_ID, @@ -9,11 +9,11 @@ const { exports.fetch = async function(ctx) { const database = new CouchDB(ctx.user.instanceId) - const data = await database.query("database/by_type", { - include_docs: true, - key: ["user"], - }) - + const data = await database.allDocs( + getUserParams(null, { + include_docs: true, + }) + ) ctx.body = data.rows.map(row => row.doc) } @@ -31,7 +31,7 @@ exports.create = async function(ctx) { if (!accessLevel) ctx.throw(400, "Invalid Access Level") const user = { - _id: getUserId(username), + _id: generateUserID(username), username, password: await bcrypt.hash(password), name: name || username, @@ -80,14 +80,14 @@ exports.update = async function(ctx) { exports.destroy = async function(ctx) { const database = new CouchDB(ctx.user.instanceId) - await database.destroy(getUserId(ctx.params.username)) + await database.destroy(generateUserID(ctx.params.username)) ctx.message = `User ${ctx.params.username} deleted.` ctx.status = 200 } exports.find = async function(ctx) { const database = new CouchDB(ctx.user.instanceId) - const user = await database.get(getUserId(ctx.params.username)) + const user = await database.get(generateUserID(ctx.params.username)) ctx.body = { username: user.username, name: user.name, diff --git a/packages/server/src/api/controllers/view/index.js b/packages/server/src/api/controllers/view/index.js index 260197aae7..d2ce3b0835 100644 --- a/packages/server/src/api/controllers/view/index.js +++ b/packages/server/src/api/controllers/view/index.js @@ -11,18 +11,11 @@ const controller = { const designDoc = await db.get("_design/database") const response = [] - for (let name in designDoc.views) { - if ( - !name.startsWith("all") && - name !== "by_type" && - name !== "by_username" && - name !== "by_automation_trigger" - ) { - response.push({ - name, - ...designDoc.views[name], - }) - } + for (let name of Object.keys(designDoc.views)) { + response.push({ + name, + ...designDoc.views[name], + }) } ctx.body = response diff --git a/packages/server/src/automations/triggers.js b/packages/server/src/automations/triggers.js index 4b213643d2..7da4ae3616 100644 --- a/packages/server/src/automations/triggers.js +++ b/packages/server/src/automations/triggers.js @@ -90,11 +90,18 @@ async function queueRelevantRecordAutomations(event, eventType) { throw `No instanceId specified for ${eventType} - check event emitters.` } const db = new CouchDB(event.instanceId) - const automationsToTrigger = await db.allDocs( + let automations = await db.allDocs( getAutomationParams(null, { include_docs: true }) ) - const automations = automationsToTrigger.rows.map(wf => wf.doc) + // filter down to the correct event type + automations = automations.rows + .map(automation => automation.doc) + .filter(automation => { + const trigger = automation.definition.trigger + return trigger && trigger.event === eventType + }) + for (let automation of automations) { let automationDef = automation.definition let automationTrigger = automationDef ? automationDef.trigger : {} diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index 8ea40b9757..f3ed3ad2dc 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -1,3 +1,5 @@ +const newid = require("./newid") + const DocumentTypes = { MODEL: "model", RECORD: "record", @@ -12,6 +14,15 @@ exports.DocumentTypes = DocumentTypes const UNICODE_MAX = "\ufff0" +/** + * If creating DB allDocs/query params with only a single input this can be used, this + * is usually the case for top level documents like models, automations, users etc. + * @param {string} docType The type of document which input params are being built for, e.g. user, + * link, app, model and so on. + * @param {string|null} input The input if looking for a particular entry. + * @param {object} otherProps Add any other properties onto the request, e.g. include_docs. + * @returns {object} Parameters which can then be used with an allDocs request. + */ function singleInputParams(docType, input, otherProps = {}) { if (input == null) { input = "" @@ -23,17 +34,32 @@ function singleInputParams(docType, input, otherProps = {}) { } } -exports.getModelParams = (modelId, otherProps = {}) => { +/** + * Gets parameters for retrieving models, this is a utility function for the singleInputParams function. + */ +exports.getModelParams = (modelId = null, otherProps = {}) => { return singleInputParams(DocumentTypes.MODEL, modelId, otherProps) } -exports.generateModelID = modelId => { - return `${DocumentTypes.MODEL}:${modelId}` +/** + * Generates a new model ID. + * @returns {string} The new model ID which the model doc can be stored under. + */ +exports.generateModelID = () => { + return `${DocumentTypes.MODEL}:${newid()}` } -exports.getRecordParams = (modelId, recordId, otherProps = {}) => { - if (modelId == null && recordId != null) { - throw "Cannot build key for record ID without a model ID" +/** + * Gets the DB allDocs/query params for retrieving a record. + * @param {string} modelId The model in which the records have been stored. + * @param {string|null} recordId The ID of the record which is being specifically queried for. This can be + * left null to get all the records in the model. + * @param {object} otherProps Any other properties to add to the request. + * @returns {object} Parameters which can then be used with an allDocs request. + */ +exports.getRecordParams = (modelId, recordId = null, otherProps = {}) => { + if (modelId == null) { + throw "Cannot build params for records without a model ID" } const endOfKey = recordId == null ? `${modelId}:` : `${modelId}:${recordId}` return { @@ -43,44 +69,86 @@ exports.getRecordParams = (modelId, recordId, otherProps = {}) => { } } -exports.generateRecordID = (modelId, recordId) => { - return `${DocumentTypes.RECORD}:${modelId}:${recordId}` +/** + * Gets a new record ID for the specified model. + * @param {string} modelId The model which the record is being created for. + * @returns {string} The new ID which a record doc can be stored under. + */ +exports.generateRecordID = modelId => { + return `${DocumentTypes.RECORD}:${modelId}:${newid()}` } -exports.getUserParams = (username, otherProps = {}) => { +/** + * Gets parameters for retrieving users, this is a utility function for the singleInputParams function. + */ +exports.getUserParams = (username = null, otherProps = {}) => { return singleInputParams(DocumentTypes.USER, username, otherProps) } +/** + * Generates a new user ID based on the passed in username. + * @param {string} username The username which the ID is going to be built up of. + * @returns {string} The new user ID which the user doc can be stored under. + */ exports.generateUserID = username => { return `${DocumentTypes.USER}:${username}` } -exports.getAutomationParams = (automationId, otherProps = {}) => { +/** + * Gets parameters for retrieving automations, this is a utility function for the singleInputParams function. + */ +exports.getAutomationParams = (automationId = null, otherProps = {}) => { return singleInputParams(DocumentTypes.AUTOMATION, automationId, otherProps) } -exports.generateAutomationID = automationId => { - return `${DocumentTypes.AUTOMATION}:${automationId}` +/** + * Generates a new automation ID. + * @returns {string} The new automation ID which the automation doc can be stored under. + */ +exports.generateAutomationID = () => { + return `${DocumentTypes.AUTOMATION}:${newid()}` } -// for now link records still have their own view as we can walk multiple directions +/** + * Generates a new link doc ID. This is currently not usable with the alldocs call, + * instead a view is built to make walking to tree easier. + * @param {string} modelId1 The ID of the linker model. + * @param {string} modelId2 The ID of the linked model. + * @param {string} recordId1 The ID of the linker record. + * @param {string} recordId2 The ID of the linked record. + * @returns {string} The new link doc ID which the automation doc can be stored under. + */ exports.generateLinkID = (modelId1, modelId2, recordId1, recordId2) => { return `${DocumentTypes.AUTOMATION}:${modelId1}:${modelId2}:${recordId1}:${recordId2}` } -exports.generateAppID = appId => { - return `${DocumentTypes.APP}:${appId}` +/** + * Generates a new app ID. + * @returns {string} The new app ID which the app doc can be stored under. + */ +exports.generateAppID = () => { + return `${DocumentTypes.APP}:${newid()}` } -exports.getAppParams = (appId, otherProps = {}) => { +/** + * Gets parameters for retrieving apps, this is a utility function for the singleInputParams function. + */ +exports.getAppParams = (appId = null, otherProps = {}) => { return singleInputParams(DocumentTypes.APP, appId, otherProps) } -exports.generateAccessLevelID = accessLevelId => { - return `${DocumentTypes.ACCESS_LEVEL}:${accessLevelId}` +/** + * Generates a new access level ID. + * @returns {string} The new access level ID which the access level doc can be stored under. + */ +exports.generateAccessLevelID = () => { + return `${DocumentTypes.ACCESS_LEVEL}:${newid()}` } -exports.getAccessLevelParams = (accessLevelId, otherProps) => { +/** + * Gets parameters for retrieving an access level, this is a utility function for the singleInputParams function. + */ +exports.getAccessLevelParams = (accessLevelId = null, otherProps = {}) => { return singleInputParams( DocumentTypes.ACCESS_LEVEL, accessLevelId,