1
0
Fork 0
mirror of synced 2024-06-01 18:20:18 +12:00
budibase/packages/auth/src/db/utils.js

172 lines
4.4 KiB
JavaScript
Raw Normal View History

2021-04-19 22:34:07 +12:00
const { newid } = require("../hashing")
exports.ViewNames = {
USER_BY_EMAIL: "by_email",
}
2021-04-07 22:33:16 +12:00
exports.StaticDatabases = {
GLOBAL: {
name: "global-db",
2021-04-07 22:33:16 +12:00
},
}
const DocumentTypes = {
USER: "us",
APP: "app",
2021-04-19 22:34:07 +12:00
GROUP: "group",
2021-04-21 05:14:36 +12:00
CONFIG: "config",
TEMPLATE: "template",
2021-04-07 22:33:16 +12:00
}
exports.DocumentTypes = DocumentTypes
2021-04-07 22:33:16 +12:00
const UNICODE_MAX = "\ufff0"
const SEPARATOR = "_"
exports.SEPARATOR = SEPARATOR
2021-04-19 22:34:07 +12:00
/**
* Generates a new group ID.
* @returns {string} The new group ID which the group doc can be stored under.
*/
exports.generateGroupID = () => {
return `${DocumentTypes.GROUP}${SEPARATOR}${newid()}`
}
2021-04-07 22:33:16 +12:00
/**
2021-04-20 03:16:46 +12:00
* Gets parameters for retrieving groups.
*/
exports.getGroupParams = (id = "", otherProps = {}) => {
return {
...otherProps,
startkey: `${DocumentTypes.GROUP}${SEPARATOR}${id}`,
endkey: `${DocumentTypes.GROUP}${SEPARATOR}${id}${UNICODE_MAX}`,
}
}
/**
* Generates a new global user ID.
* @returns {string} The new user ID which the user doc can be stored under.
*/
2021-05-04 22:32:22 +12:00
exports.generateGlobalUserID = id => {
2021-04-22 08:08:04 +12:00
return `${DocumentTypes.USER}${SEPARATOR}${id || newid()}`
}
2021-04-20 03:16:46 +12:00
/**
* Gets parameters for retrieving users.
2021-04-07 22:33:16 +12:00
*/
exports.getGlobalUserParams = (globalId, otherProps = {}) => {
if (!globalId) {
globalId = ""
}
2021-04-07 22:33:16 +12:00
return {
...otherProps,
startkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}`,
endkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}${UNICODE_MAX}`,
2021-04-07 22:33:16 +12:00
}
}
/**
* Generates a template ID.
* @param ownerId The owner/user of the template, this could be global or a group level.
*/
2021-05-04 22:32:22 +12:00
exports.generateTemplateID = ownerId => {
return `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${newid()}`
}
/**
* Gets parameters for retrieving templates. Owner ID must be specified, either global or a group level.
*/
exports.getTemplateParams = (ownerId, templateId, otherProps = {}) => {
if (!templateId) {
templateId = ""
}
2021-04-22 05:15:57 +12:00
let final
if (templateId) {
final = templateId
} else {
final = `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${SEPARATOR}`
}
2021-04-07 22:33:16 +12:00
return {
...otherProps,
startkey: final,
endkey: `${final}${UNICODE_MAX}`,
2021-04-07 22:33:16 +12:00
}
}
2021-04-21 05:14:36 +12:00
/**
* Generates a new configuration ID.
* @returns {string} The new configuration ID which the config doc can be stored under.
*/
2021-04-23 00:46:54 +12:00
const generateConfigID = ({ type, group, user }) => {
2021-04-22 22:45:22 +12:00
const scope = [type, group, user].filter(Boolean).join(SEPARATOR)
2021-04-21 05:14:36 +12:00
2021-04-22 22:45:22 +12:00
return `${DocumentTypes.CONFIG}${SEPARATOR}${scope}`
2021-04-21 05:14:36 +12:00
}
/**
* Gets parameters for retrieving configurations.
*/
2021-04-23 00:46:54 +12:00
const getConfigParams = ({ type, group, user }, otherProps = {}) => {
2021-04-22 22:45:22 +12:00
const scope = [type, group, user].filter(Boolean).join(SEPARATOR)
2021-04-21 05:14:36 +12:00
return {
...otherProps,
2021-04-22 22:45:22 +12:00
startkey: `${DocumentTypes.CONFIG}${SEPARATOR}${scope}`,
endkey: `${DocumentTypes.CONFIG}${SEPARATOR}${scope}${UNICODE_MAX}`,
2021-04-21 05:14:36 +12:00
}
}
2021-04-23 00:46:54 +12:00
/**
* Returns the most granular configuration document from the DB based on the type, group and userID passed.
2021-04-23 01:53:19 +12:00
* @param {Object} db - db instance to query
2021-04-23 00:46:54 +12:00
* @param {Object} scopes - the type, group and userID scopes of the configuration.
* @returns The most granular configuration document based on the scope.
*/
const getScopedFullConfig = async function (db, { type, user, group }) {
2021-04-23 00:46:54 +12:00
const response = await db.allDocs(
getConfigParams(
{ type, user, group },
{
include_docs: true,
}
)
)
2021-05-05 04:31:06 +12:00
function determineScore(row) {
2021-04-23 01:07:00 +12:00
const config = row.doc
2021-04-23 00:46:54 +12:00
// Config is specific to a user and a group
if (config._id.includes(generateConfigID({ type, user, group }))) {
2021-05-05 04:31:06 +12:00
return 4
2021-04-23 01:07:00 +12:00
} else if (config._id.includes(generateConfigID({ type, user }))) {
// Config is specific to a user only
2021-05-05 04:31:06 +12:00
return 3
2021-04-23 01:07:00 +12:00
} else if (config._id.includes(generateConfigID({ type, group }))) {
// Config is specific to a group only
2021-05-05 04:31:06 +12:00
return 2
2021-04-23 01:07:00 +12:00
} else if (config._id.includes(generateConfigID({ type }))) {
// Config is specific to a type only
2021-05-05 04:31:06 +12:00
return 1
2021-04-23 00:46:54 +12:00
}
2021-05-05 04:31:06 +12:00
return 0
}
2021-04-23 00:46:54 +12:00
2021-04-23 01:07:00 +12:00
// Find the config with the most granular scope based on context
2021-05-05 05:14:13 +12:00
const scopedConfig = response.rows.sort(
(a, b) => determineScore(a) - determineScore(b)
)[0]
2021-04-23 01:07:00 +12:00
return scopedConfig && scopedConfig.doc
2021-04-23 00:46:54 +12:00
}
async function getScopedConfig(db, params) {
const configDoc = await getScopedFullConfig(db, params)
return configDoc && configDoc.config ? configDoc.config : configDoc
}
exports.getScopedConfig = getScopedConfig
2021-04-23 00:46:54 +12:00
exports.generateConfigID = generateConfigID
exports.getConfigParams = getConfigParams
exports.getScopedFullConfig = getScopedFullConfig