Some updates to RBAC backend, try to make switch to object support level -> roleID.
This commit is contained in:
parent
a3ae17be8e
commit
091b4ee95d
|
@ -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]
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue