Fixing an issue with RBAC, there was a mutable issue where a server builtin resource was getting updated, fixed this by not exposing the mutable structure, instead exposing a function which provides a new object everytime.
This commit is contained in:
parent
80ebb9a740
commit
4f1a0ac645
|
@ -1,5 +1,5 @@
|
||||||
const {
|
const {
|
||||||
BUILTIN_PERMISSIONS,
|
getBuiltinPermissions,
|
||||||
PermissionLevels,
|
PermissionLevels,
|
||||||
isPermissionLevelHigherThanRead,
|
isPermissionLevelHigherThanRead,
|
||||||
higherPermission,
|
higherPermission,
|
||||||
|
@ -8,11 +8,10 @@ const {
|
||||||
isBuiltin,
|
isBuiltin,
|
||||||
getDBRoleID,
|
getDBRoleID,
|
||||||
getExternalRoleID,
|
getExternalRoleID,
|
||||||
BUILTIN_ROLES,
|
getBuiltinRoles,
|
||||||
} = require("../../utilities/security/roles")
|
} = require("../../utilities/security/roles")
|
||||||
const { getRoleParams } = require("../../db/utils")
|
const { getRoleParams } = require("../../db/utils")
|
||||||
const CouchDB = require("../../db")
|
const CouchDB = require("../../db")
|
||||||
const { cloneDeep } = require("lodash/fp")
|
|
||||||
const {
|
const {
|
||||||
CURRENTLY_SUPPORTED_LEVELS,
|
CURRENTLY_SUPPORTED_LEVELS,
|
||||||
getBasePermissions,
|
getBasePermissions,
|
||||||
|
@ -65,7 +64,7 @@ async function updatePermissionOnRole(
|
||||||
|
|
||||||
// the permission is for a built in, make sure it exists
|
// the permission is for a built in, make sure it exists
|
||||||
if (isABuiltin && !dbRoles.some(role => role._id === dbRoleId)) {
|
if (isABuiltin && !dbRoles.some(role => role._id === dbRoleId)) {
|
||||||
const builtin = cloneDeep(BUILTIN_ROLES[roleId])
|
const builtin = getBuiltinRoles()[roleId]
|
||||||
builtin._id = getDBRoleID(builtin._id)
|
builtin._id = getDBRoleID(builtin._id)
|
||||||
dbRoles.push(builtin)
|
dbRoles.push(builtin)
|
||||||
}
|
}
|
||||||
|
@ -110,7 +109,7 @@ async function updatePermissionOnRole(
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetchBuiltin = function(ctx) {
|
exports.fetchBuiltin = function(ctx) {
|
||||||
ctx.body = Object.values(BUILTIN_PERMISSIONS)
|
ctx.body = Object.values(getBuiltinPermissions())
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.fetchLevels = function(ctx) {
|
exports.fetchLevels = function(ctx) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const CouchDB = require("../../db")
|
const CouchDB = require("../../db")
|
||||||
const {
|
const {
|
||||||
BUILTIN_ROLES,
|
getBuiltinRoles,
|
||||||
BUILTIN_ROLE_IDS,
|
BUILTIN_ROLE_IDS,
|
||||||
Role,
|
Role,
|
||||||
getRole,
|
getRole,
|
||||||
|
@ -58,10 +58,11 @@ exports.fetch = async function(ctx) {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
let roles = body.rows.map(row => row.doc)
|
let roles = body.rows.map(row => row.doc)
|
||||||
|
const builtinRoles = getBuiltinRoles()
|
||||||
|
|
||||||
// need to combine builtin with any DB record of them (for sake of permissions)
|
// need to combine builtin with any DB record of them (for sake of permissions)
|
||||||
for (let builtinRoleId of EXTERNAL_BUILTIN_ROLE_IDS) {
|
for (let builtinRoleId of EXTERNAL_BUILTIN_ROLE_IDS) {
|
||||||
const builtinRole = BUILTIN_ROLES[builtinRoleId]
|
const builtinRole = builtinRoles[builtinRoleId]
|
||||||
const dbBuiltin = roles.filter(
|
const dbBuiltin = roles.filter(
|
||||||
dbRole => getExternalRoleID(dbRole._id) === builtinRoleId
|
dbRole => getExternalRoleID(dbRole._id) === builtinRoleId
|
||||||
)[0]
|
)[0]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const jwt = require("jsonwebtoken")
|
const jwt = require("jsonwebtoken")
|
||||||
const STATUS_CODES = require("../utilities/statusCodes")
|
const STATUS_CODES = require("../utilities/statusCodes")
|
||||||
const { getRole, BUILTIN_ROLES } = require("../utilities/security/roles")
|
const { getRole, getBuiltinRoles } = require("../utilities/security/roles")
|
||||||
const { AuthTypes } = require("../constants")
|
const { AuthTypes } = require("../constants")
|
||||||
const {
|
const {
|
||||||
getAppId,
|
getAppId,
|
||||||
|
@ -20,6 +20,7 @@ module.exports = async (ctx, next) => {
|
||||||
// we hold it in state as a
|
// we hold it in state as a
|
||||||
let appId = getAppId(ctx)
|
let appId = getAppId(ctx)
|
||||||
const cookieAppId = ctx.cookies.get(getCookieName("currentapp"))
|
const cookieAppId = ctx.cookies.get(getCookieName("currentapp"))
|
||||||
|
const builtinRoles = getBuiltinRoles()
|
||||||
if (appId && cookieAppId !== appId) {
|
if (appId && cookieAppId !== appId) {
|
||||||
setCookie(ctx, appId, "currentapp")
|
setCookie(ctx, appId, "currentapp")
|
||||||
} else if (cookieAppId) {
|
} else if (cookieAppId) {
|
||||||
|
@ -40,7 +41,7 @@ module.exports = async (ctx, next) => {
|
||||||
ctx.appId = appId
|
ctx.appId = appId
|
||||||
ctx.user = {
|
ctx.user = {
|
||||||
appId,
|
appId,
|
||||||
role: BUILTIN_ROLES.PUBLIC,
|
role: builtinRoles.PUBLIC,
|
||||||
}
|
}
|
||||||
await next()
|
await next()
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const { flatten } = require("lodash")
|
const { flatten } = require("lodash")
|
||||||
|
const { cloneDeep } = require("lodash/fp")
|
||||||
|
|
||||||
const PermissionLevels = {
|
const PermissionLevels = {
|
||||||
READ: "read",
|
READ: "read",
|
||||||
|
@ -70,7 +71,7 @@ exports.BUILTIN_PERMISSION_IDS = {
|
||||||
POWER: "power",
|
POWER: "power",
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.BUILTIN_PERMISSIONS = {
|
const BUILTIN_PERMISSIONS = {
|
||||||
PUBLIC: {
|
PUBLIC: {
|
||||||
_id: exports.BUILTIN_PERMISSION_IDS.PUBLIC,
|
_id: exports.BUILTIN_PERMISSION_IDS.PUBLIC,
|
||||||
name: "Public",
|
name: "Public",
|
||||||
|
@ -121,8 +122,12 @@ exports.BUILTIN_PERMISSIONS = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.getBuiltinPermissions = () => {
|
||||||
|
return cloneDeep(BUILTIN_PERMISSIONS)
|
||||||
|
}
|
||||||
|
|
||||||
exports.getBuiltinPermissionByID = id => {
|
exports.getBuiltinPermissionByID = id => {
|
||||||
const perms = Object.values(exports.BUILTIN_PERMISSIONS)
|
const perms = Object.values(BUILTIN_PERMISSIONS)
|
||||||
return perms.find(perm => perm._id === id)
|
return perms.find(perm => perm._id === id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +160,7 @@ exports.doesHaveResourcePermission = (
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.doesHaveBasePermission = (permType, permLevel, permissionIds) => {
|
exports.doesHaveBasePermission = (permType, permLevel, permissionIds) => {
|
||||||
const builtins = Object.values(exports.BUILTIN_PERMISSIONS)
|
const builtins = Object.values(BUILTIN_PERMISSIONS)
|
||||||
let permissions = flatten(
|
let permissions = flatten(
|
||||||
builtins
|
builtins
|
||||||
.filter(builtin => permissionIds.indexOf(builtin._id) !== -1)
|
.filter(builtin => permissionIds.indexOf(builtin._id) !== -1)
|
||||||
|
|
|
@ -26,7 +26,7 @@ Role.prototype.addInheritance = function(inherits) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.BUILTIN_ROLES = {
|
const BUILTIN_ROLES = {
|
||||||
ADMIN: new Role(BUILTIN_IDS.ADMIN, "Admin")
|
ADMIN: new Role(BUILTIN_IDS.ADMIN, "Admin")
|
||||||
.addPermission(BUILTIN_PERMISSION_IDS.ADMIN)
|
.addPermission(BUILTIN_PERMISSION_IDS.ADMIN)
|
||||||
.addInheritance(BUILTIN_IDS.POWER),
|
.addInheritance(BUILTIN_IDS.POWER),
|
||||||
|
@ -44,11 +44,15 @@ exports.BUILTIN_ROLES = {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.BUILTIN_ROLE_ID_ARRAY = Object.values(exports.BUILTIN_ROLES).map(
|
exports.getBuiltinRoles = () => {
|
||||||
|
return cloneDeep(BUILTIN_ROLES)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.BUILTIN_ROLE_ID_ARRAY = Object.values(BUILTIN_ROLES).map(
|
||||||
role => role._id
|
role => role._id
|
||||||
)
|
)
|
||||||
|
|
||||||
exports.BUILTIN_ROLE_NAME_ARRAY = Object.values(exports.BUILTIN_ROLES).map(
|
exports.BUILTIN_ROLE_NAME_ARRAY = Object.values(BUILTIN_ROLES).map(
|
||||||
role => role.name
|
role => role.name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,17 +64,18 @@ function isBuiltin(role) {
|
||||||
* Works through the inheritance ranks to see how far up the builtin stack this ID is.
|
* Works through the inheritance ranks to see how far up the builtin stack this ID is.
|
||||||
*/
|
*/
|
||||||
function builtinRoleToNumber(id) {
|
function builtinRoleToNumber(id) {
|
||||||
|
const builtins = exports.getBuiltinRoles()
|
||||||
const MAX = Object.values(BUILTIN_IDS).length + 1
|
const MAX = Object.values(BUILTIN_IDS).length + 1
|
||||||
if (id === BUILTIN_IDS.ADMIN || id === BUILTIN_IDS.BUILDER) {
|
if (id === BUILTIN_IDS.ADMIN || id === BUILTIN_IDS.BUILDER) {
|
||||||
return MAX
|
return MAX
|
||||||
}
|
}
|
||||||
let role = exports.BUILTIN_ROLES[id],
|
let role = builtins,
|
||||||
count = 0
|
count = 0
|
||||||
do {
|
do {
|
||||||
if (!role) {
|
if (!role) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
role = exports.BUILTIN_ROLES[role.inherits]
|
role = builtins[role.inherits]
|
||||||
count++
|
count++
|
||||||
} while (role !== null)
|
} while (role !== null)
|
||||||
return count
|
return count
|
||||||
|
@ -107,7 +112,7 @@ exports.getRole = async (appId, roleId) => {
|
||||||
// but can be extended by a doc stored about them (e.g. permissions)
|
// but can be extended by a doc stored about them (e.g. permissions)
|
||||||
if (isBuiltin(roleId)) {
|
if (isBuiltin(roleId)) {
|
||||||
role = cloneDeep(
|
role = cloneDeep(
|
||||||
Object.values(exports.BUILTIN_ROLES).find(role => role._id === roleId)
|
Object.values(BUILTIN_ROLES).find(role => role._id === roleId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -6,7 +6,7 @@ const {
|
||||||
} = require("../../utilities/security/permissions")
|
} = require("../../utilities/security/permissions")
|
||||||
const {
|
const {
|
||||||
lowerBuiltinRoleID,
|
lowerBuiltinRoleID,
|
||||||
BUILTIN_ROLES,
|
getBuiltinRoles,
|
||||||
} = require("../../utilities/security/roles")
|
} = require("../../utilities/security/roles")
|
||||||
const { DocumentTypes } = require("../../db/utils")
|
const { DocumentTypes } = require("../../db/utils")
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ exports.getPermissionType = resourceId => {
|
||||||
exports.getBasePermissions = resourceId => {
|
exports.getBasePermissions = resourceId => {
|
||||||
const type = exports.getPermissionType(resourceId)
|
const type = exports.getPermissionType(resourceId)
|
||||||
const permissions = {}
|
const permissions = {}
|
||||||
for (let [roleId, role] of Object.entries(BUILTIN_ROLES)) {
|
for (let [roleId, role] of Object.entries(getBuiltinRoles())) {
|
||||||
if (!role.permissionId) {
|
if (!role.permissionId) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue