From 334b4b1696cb04e1722c3b6db8bc5638c6890546 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 9 Oct 2020 09:47:37 +0100 Subject: [PATCH] Update to IDs as has been discussed, to change them from colons (:) to underscores (_) as this is more URL, S3 and file system safe. Also shortening most prefixes down to two characters. --- packages/server/src/api/controllers/record.js | 9 +++- packages/server/src/db/utils.js | 41 +++++++++++-------- .../server/src/utilities/sanitisedPath.js | 12 ++++++ 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index e7718665e2..473bb4f413 100644 --- a/packages/server/src/api/controllers/record.js +++ b/packages/server/src/api/controllers/record.js @@ -1,10 +1,15 @@ const CouchDB = require("../../db") const validateJs = require("validate.js") const linkRecords = require("../../db/linkedRecords") -const { getRecordParams, generateRecordID } = require("../../db/utils") +const { + getRecordParams, + generateRecordID, + DocumentTypes, + SEPARATOR, +} = require("../../db/utils") const { cloneDeep } = require("lodash") -const MODEL_VIEW_BEGINS_WITH = "all_model:" +const MODEL_VIEW_BEGINS_WITH = `all${SEPARATOR}${DocumentTypes.MODEL}${SEPARATOR}` validateJs.extend(validateJs.validators.datetime, { parse: function(value) { diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index e66eb7624f..7c55da43ff 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -1,18 +1,20 @@ const newid = require("./newid") +const UNICODE_MAX = "\ufff0" +const SEPARATOR = "_" + const DocumentTypes = { - MODEL: "model", - RECORD: "record", - USER: "user", - AUTOMATION: "automation", - LINK: "link", + MODEL: "mo", + RECORD: "re", + USER: "us", + AUTOMATION: "au", + LINK: "li", APP: "app", - ACCESS_LEVEL: "accesslevel", + ACCESS_LEVEL: "ac", } exports.DocumentTypes = DocumentTypes - -const UNICODE_MAX = "\ufff0" +exports.SEPARATOR = SEPARATOR /** * If creating DB allDocs/query params with only a single top level ID this can be used, this @@ -32,8 +34,8 @@ function getDocParams(docType, docId = null, otherProps = {}) { } return { ...otherProps, - startkey: `${docType}:${docId}`, - endkey: `${docType}:${docId}${UNICODE_MAX}`, + startkey: `${docType}${SEPARATOR}${docId}`, + endkey: `${docType}${SEPARATOR}${docId}${UNICODE_MAX}`, } } @@ -49,7 +51,7 @@ exports.getModelParams = (modelId = null, otherProps = {}) => { * @returns {string} The new model ID which the model doc can be stored under. */ exports.generateModelID = () => { - return `${DocumentTypes.MODEL}:${newid()}` + return `${DocumentTypes.MODEL}${SEPARATOR}${newid()}` } /** @@ -64,7 +66,10 @@ 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}` + const endOfKey = + recordId == null + ? `${modelId}${SEPARATOR}` + : `${modelId}${SEPARATOR}${recordId}` return getDocParams(DocumentTypes.RECORD, endOfKey, otherProps) } @@ -74,7 +79,7 @@ exports.getRecordParams = (modelId, recordId = null, otherProps = {}) => { * @returns {string} The new ID which a record doc can be stored under. */ exports.generateRecordID = modelId => { - return `${DocumentTypes.RECORD}:${modelId}:${newid()}` + return `${DocumentTypes.RECORD}${SEPARATOR}${modelId}${SEPARATOR}${newid()}` } /** @@ -90,7 +95,7 @@ exports.getUserParams = (username = null, otherProps = {}) => { * @returns {string} The new user ID which the user doc can be stored under. */ exports.generateUserID = username => { - return `${DocumentTypes.USER}:${username}` + return `${DocumentTypes.USER}${SEPARATOR}${username}` } /** @@ -105,7 +110,7 @@ exports.getAutomationParams = (automationId = null, otherProps = {}) => { * @returns {string} The new automation ID which the automation doc can be stored under. */ exports.generateAutomationID = () => { - return `${DocumentTypes.AUTOMATION}:${newid()}` + return `${DocumentTypes.AUTOMATION}${SEPARATOR}${newid()}` } /** @@ -118,7 +123,7 @@ exports.generateAutomationID = () => { * @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}` + return `${DocumentTypes.AUTOMATION}${SEPARATOR}${modelId1}${SEPARATOR}${modelId2}${SEPARATOR}${recordId1}${SEPARATOR}${recordId2}` } /** @@ -126,7 +131,7 @@ exports.generateLinkID = (modelId1, modelId2, recordId1, recordId2) => { * @returns {string} The new app ID which the app doc can be stored under. */ exports.generateAppID = () => { - return `${DocumentTypes.APP}:${newid()}` + return `${DocumentTypes.APP}${SEPARATOR}${newid()}` } /** @@ -141,7 +146,7 @@ exports.getAppParams = (appId = null, otherProps = {}) => { * @returns {string} The new access level ID which the access level doc can be stored under. */ exports.generateAccessLevelID = () => { - return `${DocumentTypes.ACCESS_LEVEL}:${newid()}` + return `${DocumentTypes.ACCESS_LEVEL}${SEPARATOR}${newid()}` } /** diff --git a/packages/server/src/utilities/sanitisedPath.js b/packages/server/src/utilities/sanitisedPath.js index c2c304aad9..840fa134f2 100644 --- a/packages/server/src/utilities/sanitisedPath.js +++ b/packages/server/src/utilities/sanitisedPath.js @@ -1,11 +1,23 @@ const path = require("path") const regex = new RegExp(/:(?![\\/])/g) +// set a limit on path depth, just incase recursion is occurring +const MAX_ARGS = 50 function sanitiseArgs(args) { let sanitised = [] + let count = 0 for (let arg of args) { + // if a known string is found don't continue, can't operate on it + if (typeof arg !== "string") { + throw "Sanitisation of paths can only occur on strings" + } + // maximum number of path args have been iterated on + if (count > MAX_ARGS) { + break + } sanitised.push(arg.replace(regex, "")) + count++ } return sanitised }