2020-11-11 18:34:15 +01:00
|
|
|
const { flatten } = require("lodash")
|
2021-02-12 21:34:54 +01:00
|
|
|
const { cloneDeep } = require("lodash/fp")
|
2020-11-11 18:34:15 +01:00
|
|
|
|
|
|
|
const PermissionLevels = {
|
|
|
|
READ: "read",
|
|
|
|
WRITE: "write",
|
|
|
|
EXECUTE: "execute",
|
|
|
|
ADMIN: "admin",
|
|
|
|
}
|
|
|
|
|
2021-02-05 16:58:25 +01:00
|
|
|
// these are the global types, that govern the underlying default behaviour
|
2020-11-11 18:34:15 +01:00
|
|
|
const PermissionTypes = {
|
|
|
|
TABLE: "table",
|
|
|
|
USER: "user",
|
|
|
|
AUTOMATION: "automation",
|
|
|
|
WEBHOOK: "webhook",
|
|
|
|
BUILDER: "builder",
|
|
|
|
VIEW: "view",
|
2021-01-06 13:28:51 +01:00
|
|
|
QUERY: "query",
|
2020-11-11 18:34:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function Permission(type, level) {
|
|
|
|
this.level = level
|
|
|
|
this.type = type
|
|
|
|
}
|
|
|
|
|
2021-02-11 14:29:15 +01:00
|
|
|
function levelToNumber(perm) {
|
|
|
|
switch (perm) {
|
|
|
|
// not everything has execute privileges
|
|
|
|
case PermissionLevels.EXECUTE:
|
|
|
|
return 0
|
|
|
|
case PermissionLevels.READ:
|
|
|
|
return 1
|
|
|
|
case PermissionLevels.WRITE:
|
|
|
|
return 2
|
|
|
|
case PermissionLevels.ADMIN:
|
|
|
|
return 3
|
|
|
|
default:
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-11 18:34:15 +01:00
|
|
|
/**
|
|
|
|
* Given the specified permission level for the user return the levels they are allowed to carry out.
|
|
|
|
* @param {string} userPermLevel The permission level of the user.
|
|
|
|
* @return {string[]} All the permission levels this user is allowed to carry out.
|
|
|
|
*/
|
|
|
|
function getAllowedLevels(userPermLevel) {
|
|
|
|
switch (userPermLevel) {
|
|
|
|
case PermissionLevels.EXECUTE:
|
|
|
|
return [PermissionLevels.EXECUTE]
|
2021-02-08 18:22:07 +01:00
|
|
|
case PermissionLevels.READ:
|
|
|
|
return [PermissionLevels.EXECUTE, PermissionLevels.READ]
|
|
|
|
case PermissionLevels.WRITE:
|
2020-11-11 18:34:15 +01:00
|
|
|
case PermissionLevels.ADMIN:
|
|
|
|
return [
|
|
|
|
PermissionLevels.READ,
|
|
|
|
PermissionLevels.WRITE,
|
|
|
|
PermissionLevels.EXECUTE,
|
|
|
|
]
|
|
|
|
default:
|
|
|
|
return []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-02 18:08:25 +01:00
|
|
|
exports.BUILTIN_PERMISSION_IDS = {
|
2021-02-11 19:13:09 +01:00
|
|
|
PUBLIC: "public",
|
2020-11-11 18:34:15 +01:00
|
|
|
READ_ONLY: "read_only",
|
|
|
|
WRITE: "write",
|
2020-11-12 18:06:55 +01:00
|
|
|
ADMIN: "admin",
|
|
|
|
POWER: "power",
|
2020-11-11 18:34:15 +01:00
|
|
|
}
|
|
|
|
|
2021-02-12 21:34:54 +01:00
|
|
|
const BUILTIN_PERMISSIONS = {
|
2021-02-11 19:13:09 +01:00
|
|
|
PUBLIC: {
|
|
|
|
_id: exports.BUILTIN_PERMISSION_IDS.PUBLIC,
|
|
|
|
name: "Public",
|
|
|
|
permissions: [
|
2021-02-12 10:55:37 +01:00
|
|
|
new Permission(PermissionTypes.WEBHOOK, PermissionLevels.EXECUTE),
|
2021-02-11 19:13:09 +01:00
|
|
|
],
|
|
|
|
},
|
2020-11-11 18:34:15 +01:00
|
|
|
READ_ONLY: {
|
2020-12-02 18:08:25 +01:00
|
|
|
_id: exports.BUILTIN_PERMISSION_IDS.READ_ONLY,
|
|
|
|
name: "Read only",
|
2020-11-11 18:34:15 +01:00
|
|
|
permissions: [
|
2021-01-11 22:01:21 +01:00
|
|
|
new Permission(PermissionTypes.QUERY, PermissionLevels.READ),
|
2020-11-11 18:34:15 +01:00
|
|
|
new Permission(PermissionTypes.TABLE, PermissionLevels.READ),
|
|
|
|
new Permission(PermissionTypes.VIEW, PermissionLevels.READ),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
WRITE: {
|
2020-12-02 18:08:25 +01:00
|
|
|
_id: exports.BUILTIN_PERMISSION_IDS.WRITE,
|
|
|
|
name: "Read/Write",
|
2020-11-11 18:34:15 +01:00
|
|
|
permissions: [
|
2021-01-11 22:01:21 +01:00
|
|
|
new Permission(PermissionTypes.QUERY, PermissionLevels.WRITE),
|
2020-11-11 18:34:15 +01:00
|
|
|
new Permission(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
|
|
|
new Permission(PermissionTypes.VIEW, PermissionLevels.READ),
|
|
|
|
],
|
|
|
|
},
|
2020-11-12 18:06:55 +01:00
|
|
|
POWER: {
|
2020-12-02 18:08:25 +01:00
|
|
|
_id: exports.BUILTIN_PERMISSION_IDS.POWER,
|
|
|
|
name: "Power",
|
2020-11-12 18:06:55 +01:00
|
|
|
permissions: [
|
|
|
|
new Permission(PermissionTypes.TABLE, PermissionLevels.WRITE),
|
|
|
|
new Permission(PermissionTypes.USER, PermissionLevels.READ),
|
|
|
|
new Permission(PermissionTypes.AUTOMATION, PermissionLevels.EXECUTE),
|
|
|
|
new Permission(PermissionTypes.VIEW, PermissionLevels.READ),
|
|
|
|
new Permission(PermissionTypes.WEBHOOK, PermissionLevels.READ),
|
|
|
|
],
|
|
|
|
},
|
|
|
|
ADMIN: {
|
2020-12-02 18:08:25 +01:00
|
|
|
_id: exports.BUILTIN_PERMISSION_IDS.ADMIN,
|
|
|
|
name: "Admin",
|
2020-11-12 18:06:55 +01:00
|
|
|
permissions: [
|
|
|
|
new Permission(PermissionTypes.TABLE, PermissionLevels.ADMIN),
|
|
|
|
new Permission(PermissionTypes.USER, PermissionLevels.ADMIN),
|
|
|
|
new Permission(PermissionTypes.AUTOMATION, PermissionLevels.ADMIN),
|
|
|
|
new Permission(PermissionTypes.VIEW, PermissionLevels.ADMIN),
|
|
|
|
new Permission(PermissionTypes.WEBHOOK, PermissionLevels.READ),
|
2021-01-11 22:01:21 +01:00
|
|
|
new Permission(PermissionTypes.QUERY, PermissionLevels.ADMIN),
|
2020-11-12 18:06:55 +01:00
|
|
|
],
|
|
|
|
},
|
2020-11-11 18:34:15 +01:00
|
|
|
}
|
|
|
|
|
2021-02-12 21:34:54 +01:00
|
|
|
exports.getBuiltinPermissions = () => {
|
|
|
|
return cloneDeep(BUILTIN_PERMISSIONS)
|
|
|
|
}
|
|
|
|
|
2021-02-11 11:24:37 +01:00
|
|
|
exports.getBuiltinPermissionByID = id => {
|
2021-02-12 21:34:54 +01:00
|
|
|
const perms = Object.values(BUILTIN_PERMISSIONS)
|
2021-02-11 11:24:37 +01:00
|
|
|
return perms.find(perm => perm._id === id)
|
|
|
|
}
|
|
|
|
|
2021-02-08 18:52:22 +01:00
|
|
|
exports.doesHaveResourcePermission = (
|
|
|
|
permissions,
|
|
|
|
permLevel,
|
|
|
|
{ resourceId, subResourceId }
|
|
|
|
) => {
|
|
|
|
// set foundSub to not subResourceId, incase there is no subResource
|
|
|
|
let foundMain = false,
|
2021-02-26 11:19:06 +01:00
|
|
|
foundSub = false
|
2021-02-08 18:52:22 +01:00
|
|
|
for (let [resource, level] of Object.entries(permissions)) {
|
|
|
|
const levels = getAllowedLevels(level)
|
|
|
|
if (resource === resourceId && levels.indexOf(permLevel) !== -1) {
|
|
|
|
foundMain = true
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
subResourceId &&
|
|
|
|
resource === subResourceId &&
|
|
|
|
levels.indexOf(permLevel) !== -1
|
|
|
|
) {
|
|
|
|
foundSub = true
|
|
|
|
}
|
|
|
|
// this will escape if foundMain only when no sub resource
|
|
|
|
if (foundMain && foundSub) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-02-26 11:06:02 +01:00
|
|
|
return foundMain || foundSub
|
2021-02-08 18:52:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
exports.doesHaveBasePermission = (permType, permLevel, permissionIds) => {
|
2021-02-12 21:34:54 +01:00
|
|
|
const builtins = Object.values(BUILTIN_PERMISSIONS)
|
2020-11-11 18:34:15 +01:00
|
|
|
let permissions = flatten(
|
|
|
|
builtins
|
2020-12-02 18:08:25 +01:00
|
|
|
.filter(builtin => permissionIds.indexOf(builtin._id) !== -1)
|
2020-11-11 18:34:15 +01:00
|
|
|
.map(builtin => builtin.permissions)
|
|
|
|
)
|
|
|
|
for (let permission of permissions) {
|
|
|
|
if (
|
|
|
|
permission.type === permType &&
|
|
|
|
getAllowedLevels(permission.level).indexOf(permLevel) !== -1
|
|
|
|
) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-02-08 18:22:07 +01:00
|
|
|
exports.higherPermission = (perm1, perm2) => {
|
2021-02-11 14:29:15 +01:00
|
|
|
return levelToNumber(perm1) > levelToNumber(perm2) ? perm1 : perm2
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.isPermissionLevelHigherThanRead = level => {
|
|
|
|
return levelToNumber(level) > 1
|
2021-02-08 18:22:07 +01:00
|
|
|
}
|
|
|
|
|
2020-11-11 18:34:15 +01:00
|
|
|
// utility as a lot of things need simply the builder permission
|
|
|
|
exports.BUILDER = PermissionTypes.BUILDER
|
|
|
|
exports.PermissionTypes = PermissionTypes
|
|
|
|
exports.PermissionLevels = PermissionLevels
|