Making use of the resourceId in the middleware package.
This commit is contained in:
parent
9752263e25
commit
7a65a59c78
|
@ -1,10 +1,11 @@
|
|||
const {
|
||||
BUILTIN_ROLE_IDS,
|
||||
getUserPermissionIds,
|
||||
getUserPermissions,
|
||||
} = require("../utilities/security/roles")
|
||||
const {
|
||||
PermissionTypes,
|
||||
doesHavePermission,
|
||||
doesHaveResourcePermission,
|
||||
doesHaveBasePermission,
|
||||
} = require("../utilities/security/permissions")
|
||||
const env = require("../environment")
|
||||
const { isAPIKeyValid } = require("../utilities/security/apikey")
|
||||
|
@ -14,6 +15,10 @@ const ADMIN_ROLES = [BUILTIN_ROLE_IDS.ADMIN, BUILTIN_ROLE_IDS.BUILDER]
|
|||
|
||||
const LOCAL_PASS = new RegExp(["webhooks/trigger", "webhooks/schema"].join("|"))
|
||||
|
||||
function hasResource(ctx) {
|
||||
return ctx.resourceId != null
|
||||
}
|
||||
|
||||
module.exports = (permType, permLevel = null) => async (ctx, next) => {
|
||||
// webhooks can pass locally
|
||||
if (!env.CLOUD && LOCAL_PASS.test(ctx.request.url)) {
|
||||
|
@ -47,7 +52,10 @@ module.exports = (permType, permLevel = null) => async (ctx, next) => {
|
|||
}
|
||||
|
||||
const role = ctx.user.role
|
||||
const permissions = await getUserPermissionIds(ctx.appId, role._id)
|
||||
const { basePermissions, permissions } = await getUserPermissions(
|
||||
ctx.appId,
|
||||
role._id
|
||||
)
|
||||
if (ADMIN_ROLES.indexOf(role._id) !== -1) {
|
||||
return next()
|
||||
}
|
||||
|
@ -56,7 +64,14 @@ module.exports = (permType, permLevel = null) => async (ctx, next) => {
|
|||
ctx.throw(403, "Not Authorized")
|
||||
}
|
||||
|
||||
if (!doesHavePermission(permType, permLevel, permissions)) {
|
||||
if (
|
||||
hasResource(ctx) &&
|
||||
doesHaveResourcePermission(permissions, permLevel, ctx)
|
||||
) {
|
||||
return next()
|
||||
}
|
||||
|
||||
if (!doesHaveBasePermission(permType, permLevel, basePermissions)) {
|
||||
ctx.throw(403, "User does not have permission")
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,35 @@ exports.BUILTIN_PERMISSIONS = {
|
|||
},
|
||||
}
|
||||
|
||||
exports.doesHavePermission = (permType, permLevel, permissionIds) => {
|
||||
exports.doesHaveResourcePermission = (
|
||||
permissions,
|
||||
permLevel,
|
||||
{ resourceId, subResourceId }
|
||||
) => {
|
||||
// set foundSub to not subResourceId, incase there is no subResource
|
||||
let foundMain = false,
|
||||
foundSub = !subResourceId
|
||||
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
|
||||
}
|
||||
}
|
||||
return foundMain && foundSub
|
||||
}
|
||||
|
||||
exports.doesHaveBasePermission = (permType, permLevel, permissionIds) => {
|
||||
const builtins = Object.values(exports.BUILTIN_PERMISSIONS)
|
||||
let permissions = flatten(
|
||||
builtins
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
const CouchDB = require("../../db")
|
||||
const { cloneDeep } = require("lodash/fp")
|
||||
const { BUILTIN_PERMISSION_IDS } = require("./permissions")
|
||||
const {
|
||||
BUILTIN_PERMISSION_IDS,
|
||||
higherPermission,
|
||||
doesHaveBasePermission,
|
||||
} = require("./permissions")
|
||||
|
||||
const BUILTIN_IDS = {
|
||||
ADMIN: "ADMIN",
|
||||
|
@ -127,14 +131,26 @@ exports.getUserRoleHierarchy = async (appId, userRoleId) => {
|
|||
* Get all of the user permissions which could be found across the role hierarchy
|
||||
* @param appId The ID of the application from which roles should be obtained.
|
||||
* @param userRoleId The user's role ID, this can be found in their access token.
|
||||
* @returns {Promise<string[]>} A list of permission IDs these should all be unique.
|
||||
* @returns {Promise<{basePermissions: string[], permissions: Object}>} the base
|
||||
* permission IDs as well as any custom resource permissions.
|
||||
*/
|
||||
exports.getUserPermissionIds = async (appId, userRoleId) => {
|
||||
return [
|
||||
...new Set(
|
||||
(await getAllUserRoles(appId, userRoleId)).map(role => role.permissionId)
|
||||
),
|
||||
exports.getUserPermissions = async (appId, userRoleId) => {
|
||||
const rolesHierarchy = await getAllUserRoles(appId, userRoleId)
|
||||
const basePermissions = [
|
||||
...new Set(rolesHierarchy.map(role => role.permissionId)),
|
||||
]
|
||||
const permissions = {}
|
||||
for (let role of rolesHierarchy) {
|
||||
if (role.permissions) {
|
||||
for (let [resource, level] of Object.entries(role.permissions)) {
|
||||
permissions[resource] = higherPermission(permissions[resource], level)
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
basePermissions,
|
||||
permissions,
|
||||
}
|
||||
}
|
||||
|
||||
class AccessController {
|
||||
|
|
Loading…
Reference in New Issue