Some updates to RBAC backend, try to make switch to object support level -> roleID.

This commit is contained in:
mike12345567 2021-02-11 13:29:15 +00:00
parent c3840d8017
commit 6c4c70e62b
3 changed files with 72 additions and 34 deletions

View File

@ -4,11 +4,13 @@ const {
PermissionTypes,
higherPermission,
getBuiltinPermissionByID,
isPermissionLevelHigherThanRead,
} = require("../../utilities/security/permissions")
const {
isBuiltin,
getDBRoleID,
getExternalRoleID,
lowerBuiltinRoleID,
BUILTIN_ROLES,
} = require("../../utilities/security/roles")
const { getRoleParams, DocumentTypes } = require("../../db/utils")
@ -20,33 +22,31 @@ const PermissionUpdateType = {
ADD: "add",
}
function getBasePermissions(resourceId) {
const SUPPORTED_LEVELS = [PermissionLevels.WRITE, PermissionLevels.READ]
function getPermissionType(resourceId) {
const docType = DocumentTypes.filter(docType =>
resourceId.startsWith(docType)
)[0]
const levelsToFind = [PermissionLevels.WRITE, PermissionLevels.READ]
let type
switch (docType) {
case DocumentTypes.TABLE:
case DocumentTypes.ROW:
type = PermissionTypes.TABLE
break
return PermissionTypes.TABLE
case DocumentTypes.AUTOMATION:
type = PermissionTypes.AUTOMATION
break
return PermissionTypes.AUTOMATION
case DocumentTypes.WEBHOOK:
type = PermissionTypes.WEBHOOK
break
return PermissionTypes.WEBHOOK
case DocumentTypes.QUERY:
case DocumentTypes.DATASOURCE:
type = PermissionTypes.QUERY
break
return PermissionTypes.QUERY
default:
// views don't have an ID, will end up here
type = PermissionTypes.VIEW
break
return PermissionTypes.VIEW
}
}
async function getBasePermissions(resourceId) {
const type = getPermissionType(resourceId)
const permissions = {}
for (let [roleId, role] of Object.entries(BUILTIN_ROLES)) {
if (!role.permissionId) {
@ -55,10 +55,17 @@ function getBasePermissions(resourceId) {
const perms = getBuiltinPermissionByID(role.permissionId)
const typedPermission = perms.permissions.find(perm => perm.type === type)
if (typedPermission) {
// TODO: need to get the lowest role
// TODO: store the read/write with the lowest role
const level = typedPermission.level
permissions[level] = lowerBuiltinRoleID(permissions[level], roleId)
if (isPermissionLevelHigherThanRead(level)) {
permissions[PermissionLevels.READ] = lowerBuiltinRoleID(
permissions[PermissionLevels.READ],
roleId
)
}
}
}
return permissions
}
// utility function to stop this repetition - permissions always stored under roles
@ -132,7 +139,7 @@ exports.fetchBuiltin = function(ctx) {
exports.fetchLevels = function(ctx) {
// for now only provide the read/write perms externally
ctx.body = [PermissionLevels.WRITE, PermissionLevels.READ]
ctx.body = SUPPORTED_LEVELS
}
exports.fetch = async function(ctx) {
@ -167,11 +174,12 @@ exports.getResourcePerms = async function(ctx) {
)
const roles = body.rows.map(row => row.doc)
const resourcePerms = {}
for (let role of roles) {
for (let level of SUPPORTED_LEVELS) {
for (let role of roles)
// update the various roleIds in the resource permissions
if (role.permissions && role.permissions[resourceId]) {
const roleId = getExternalRoleID(role._id)
resourcePerms[roleId] = higherPermission(
resourcePerms[level] = higherPermission(
resourcePerms[roleId],
role.permissions[resourceId]
)

View File

@ -23,6 +23,22 @@ function Permission(type, level) {
this.type = type
}
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
}
}
/**
* 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.
@ -149,22 +165,11 @@ exports.doesHaveBasePermission = (permType, permLevel, permissionIds) => {
}
exports.higherPermission = (perm1, perm2) => {
function toNum(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
}
}
return toNum(perm1) > toNum(perm2) ? perm1 : perm2
return levelToNumber(perm1) > levelToNumber(perm2) ? perm1 : perm2
}
exports.isPermissionLevelHigherThanRead = level => {
return levelToNumber(level) > 1
}
// utility as a lot of things need simply the builder permission

View File

@ -222,6 +222,31 @@ exports.getExternalRoleID = roleId => {
return roleId
}
/**
* Returns whichever roleID is lower.
*/
exports.lowerRoleID = async (appId, roleId1, roleId2) => {
// TODO: need to make this function work
const MAX = Object.values(BUILTIN_IDS).length + 1
async function toNum(id) {
if (id === BUILTIN_IDS.ADMIN || id === BUILTIN_IDS.BUILDER) {
return MAX
}
let role = await exports.getRole(appId, id),
count = 0
do {
if (!role) {
break
}
role = exports.BUILTIN_ROLES[role.inherits]
count++
} while (role !== null)
return count
}
const [num1, num2] = Promise.all([toNum(roleId1), toNum(roleId2)])
return num1 > num2 ? roleId2 : roleId1
}
exports.AccessController = AccessController
exports.BUILTIN_ROLE_IDS = BUILTIN_IDS
exports.isBuiltin = isBuiltin