From 9ff998a5b185c80aa31c57836f9d86b75dcadd6f Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Mon, 15 Apr 2019 15:04:50 +0000 Subject: server crash hotfix --- server/lib/permissions/permissionhelper.js | 253 +++++++++++++++++++++++++++++ server/lib/permissions/permissionutil.js | 253 ----------------------------- 2 files changed, 253 insertions(+), 253 deletions(-) create mode 100644 server/lib/permissions/permissionhelper.js delete mode 100644 server/lib/permissions/permissionutil.js (limited to 'server/lib/permissions') diff --git a/server/lib/permissions/permissionhelper.js b/server/lib/permissions/permissionhelper.js new file mode 100644 index 0000000..db2fc35 --- /dev/null +++ b/server/lib/permissions/permissionhelper.js @@ -0,0 +1,253 @@ +/* global __appdir */ +const path = require('path') +var db = require(path.join(__appdir, 'lib', 'sequelize')) +var groupHelper = require(path.join(__appdir, 'lib', 'grouphelper')) + +module.exports = { exportFunctions } + +function exportFunctions (req, res, next) { + req.user.hasPermission = permissionName => hasPermission(req.user.id, permissionName) + req.user.getAllowedGroups = permissionName => getAllowedGroups(req.user.id, permissionName) + req.user.hasPermissionForGroup = (permissionName, groupId) => hasPermissionForGroup(req.user.id, permissionName, groupId) + req.user.getAllowedClients = permissionName => getAllowedClients(req.user.id, permissionName) + req.user.hasPermissionForClient = (permissionName, clientId) => hasPermissionForClient(req.user.id, permissionName, clientId) + next() +} + +async function isSuperadmin (userid) { + var user = await db.user.findOne({ + where: { id: userid, '$roles.permissions.name$': 'superadmin' }, + include: [{ as: 'roles', model: db.role, include: ['permissions'] }] + }) + return user !== null +} + +// Check if the user has given permission. +async function hasPermission (userid, permissionName) { + var superAdmin = await isSuperadmin(userid) + if (superAdmin) return true + var permission = permissionName.split('.') + // Wildcards + var user + if (permission[1] === '*') { + user = await db.user.findOne({ + where: { id: userid, '$roles.permissions.name$': { [db.Op.like]: permission[0] + '%' } }, + include: [{ as: 'roles', model: db.role, include: ['permissions'] }] + }) + } else { + user = await db.user.findOne({ + where: { id: userid, '$roles.permissions.name$': permissionName }, + include: [{ as: 'roles', model: db.role, include: ['permissions'] }] + }) + } + return user !== null +} + +// Get a list of GroupIDs the user has the given permission for. 0 means for all groups. +async function getAllowedGroups (userid, permissionName) { + var superAdmin = await isSuperadmin(userid) + if (superAdmin) return [0] + var user = await db.user.findOne({ + where: { id: userid, '$roles.permissions.name$': permissionName }, + include: [{ as: 'roles', model: db.role, include: ['permissions', 'groups'] }] + }) + // User doesn't have the permission + if (user === null) return [] + // User has permission, permission is not groupdependent + else if (!user.roles[0].permissions[0].groupdependent) return [0] + // User has permission, permission is groupdependent + else { + var permGrps = [] + for (let i = 0; i < user.roles.length; i++) { + var whitelist = [] + var blacklist = [] + // Fill in white- and blacklist + for (let j = 0; j < user.roles[i].groups.length; j++) { + if (user.roles[i].groups[j].role_x_group.blacklist) { + blacklist.push(user.roles[i].groups[j]) + } else { + whitelist.push(user.roles[i].groups[j]) + } + } + + // Get childs of white and blacklist groups + var whiteSubChilds = await groupHelper.getAllChildren(whitelist) + var blackSubChilds = await groupHelper.getAllChildren(blacklist) + + // Add all whitelist-ids to result. + permGrps = permGrps.concat(whitelist.map(x => x.id)) + permGrps = permGrps.concat(whiteSubChilds.subgroups.map(s => s.id)) + + // Filter out blacklist-ids from the result. + blacklist = blacklist.map(x => x.id) + blacklist = blacklist.concat(blackSubChilds.subgroups.map(x => x.id)) + for (let k = 0; k < blacklist.length; k++) { + var index = permGrps.indexOf(blacklist[k]) + if (index > -1) { + permGrps.splice(index, 1) + } + } + } + // Filter result for unique entries + return permGrps.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) + } +} + +// Check if the user has a given permission for a given group. +async function hasPermissionForGroup (userid, permissionName, groupId) { + var superAdmin = await isSuperadmin(userid) + if (superAdmin) return true + var user = await db.user.findOne({ + where: { id: userid, '$roles.permissions.name$': permissionName }, + include: [{ as: 'roles', model: db.role, include: ['permissions', 'groups'] }] + }) + // User doesn't have permission + if (user === null) return false + // User has permission, permission is not groupdependent + else if (!user.roles[0].permissions[0].groupdependent) return true + // User has permission, permission is groupdependent, check for group + else { + var result = false + var whitelist = [] + var blacklist = [] + // Fill in white- and blacklist + for (let i = 0; i < user.roles.length; i++) { + for (let j = 0; j < user.roles[i].groups.length; j++) { + if (user.roles[i].groups[j].role_x_group.blacklist) { + blacklist.push(user.roles[i].groups[j].id) + } else { + whitelist.push(user.roles[i].groups[j].id) + } + } + } + // Shortcut + if (blacklist.includes(groupId)) { + return false + } + // Remember it was found, check if any parent is in the blacklist tho. + if (whitelist.includes(groupId)) { + result = true + } + // Check parents for white-/blacklist entries. + result = await checkParents(groupId, whitelist, blacklist, result) + return result + } +} + +// Get a list of ClientIDs the user has the given permission for. 0 means for all clients. +async function getAllowedClients (userid, permissionName) { + var superAdmin = await isSuperadmin(userid) + if (superAdmin) return [0] + var user = await db.user.findOne({ + where: { id: userid, '$roles.permissions.name$': permissionName }, + include: [{ as: 'roles', model: db.role, include: ['permissions', { as: 'groups', model: db.group, include: ['clients'] }] }] + }) + // User doesn't have the permission + if (user === null) return [] + // User has permission, permission is not groupdependent + else if (!user.roles[0].permissions[0].groupdependent) return [0] + // User has permission, permission is groupdependent + else { + var permClients = [] + for (let i = 0; i < user.roles.length; i++) { + var whitelist = [] + var blacklist = [] + // Fill in white- and blacklist + for (let j = 0; j < user.roles[i].groups.length; j++) { + if (user.roles[i].groups[j].role_x_group.blacklist) { + blacklist.push(user.roles[i].groups[j]) + } else { + whitelist.push(user.roles[i].groups[j]) + } + } + + // Get childs of white and blacklist groups + var whiteSubChilds = await groupHelper.getAllChildren(whitelist) + var blackSubChilds = await groupHelper.getAllChildren(blacklist) + + // Add all whitelist-ids to result. + permClients = permClients.concat(whiteSubChilds.clients.map(s => s.id)) + + // Filter out blacklist-ids from the result. + blackSubChilds = blackSubChilds.clients.map(x => x.id) + for (let k = 0; k < blackSubChilds.length; k++) { + var index = permClients.indexOf(blackSubChilds[k]) + if (index > -1) { + permClients.splice(index, 1) + } + } + } + // Filter result for unique entries + return permClients.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) + } +} + +// Check if the user has a given permission for a given client. +async function hasPermissionForClient (userid, permissionName, clientId) { + var superAdmin = await isSuperadmin(userid) + if (superAdmin) return true + var user = await db.user.findOne({ + where: { id: userid, '$roles.permissions.name$': permissionName }, + include: [{ as: 'roles', model: db.role, include: ['permissions', { as: 'groups', model: db.group, include: ['clients'] }] }] + }) + // User doesn't have permission + if (user === null) return false + // User has permission, permission is not groupdependent + else if (!user.roles[0].permissions[0].groupdependent) return true + // User has permission, permission is groupdependent, check for client + else { + var result = false + var whitelist = [] + var blacklist = [] + // Fill in white- and blacklist + for (let i = 0; i < user.roles.length; i++) { + for (let j = 0; j < user.roles[i].groups.length; j++) { + var clients = user.roles[i].groups[j].clients.map(c => c.id) + if (user.roles[i].groups[j].role_x_group.blacklist) { + // Shortcut + if (clients.includes(clientId)) return false + blacklist.push(user.roles[i].groups[j].id) + } else { + // Remember it was found, check if any parent is in the blacklist tho. + if (clients.includes(clientId)) result = true + whitelist.push(user.roles[i].groups[j].id) + } + } + } + // Get groups the client is assigned to + var client = await db.client.findOne({ + where: { id: clientId }, + include: [{ as: 'groups', model: db.group }] + }) + var groupIds = client.groups.map(g => g.id) + // Check parents for white-/blacklist entries. + result = await checkParents(groupIds, whitelist, blacklist, result) + return result + } +} + +// Check if parents of groupIds are in the whitelist / blacklist +async function checkParents (groupIds, whitelist, blacklist, result) { + // No whitelist means the group cant be in one + if (whitelist.length === 0) return false + // No blacklist means the result can't be changed once it's true + if (blacklist.length === 0 && result) return true + + var parentIds = [] + var groups = await db.group.findAll({ where: { id: groupIds }, include: ['parents'] }) + for (let i = 0; i < groups.length; i++) { + for (let j = 0; j < groups[i].parents.length; j++) { + var id = groups[i].parents[j].id + // blacklisted + if (blacklist.includes(id)) return false + // Remember, but a further parent can still be blacklisted, so continue. + if (whitelist.includes(id)) result = true + if (!parentIds.includes(id)) parentIds.push(id) + } + } + // No further parents found, result is the result. + if (parentIds.length === 0) return result + // Check next layer of parents + result = await checkParents(parentIds, whitelist, blacklist, result) + return result +} diff --git a/server/lib/permissions/permissionutil.js b/server/lib/permissions/permissionutil.js deleted file mode 100644 index 8e91af9..0000000 --- a/server/lib/permissions/permissionutil.js +++ /dev/null @@ -1,253 +0,0 @@ -/* global __appdir */ -const path = require('path') -var db = require(path.join(__appdir, 'lib', 'sequelize')) -var groupUtil = require(path.join(__appdir, 'lib', 'grouputil')) - -module.exports = { exportFunctions } - -function exportFunctions (req, res, next) { - req.user.hasPermission = permissionName => hasPermission(req.user.id, permissionName) - req.user.getAllowedGroups = permissionName => getAllowedGroups(req.user.id, permissionName) - req.user.hasPermissionForGroup = (permissionName, groupId) => hasPermissionForGroup(req.user.id, permissionName, groupId) - req.user.getAllowedClients = permissionName => getAllowedClients(req.user.id, permissionName) - req.user.hasPermissionForClient = (permissionName, clientId) => hasPermissionForClient(req.user.id, permissionName, clientId) - next() -} - -async function isSuperadmin (userid) { - var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.name$': 'superadmin' }, - include: [{ as: 'roles', model: db.role, include: ['permissions'] }] - }) - return user !== null -} - -// Check if the user has given permission. -async function hasPermission (userid, permissionName) { - var superAdmin = await isSuperadmin(userid) - if (superAdmin) return true - var permission = permissionName.split('.') - // Wildcards - var user - if (permission[1] === '*') { - user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.name$': { [db.Op.like]: permission[0] + '%' } }, - include: [{ as: 'roles', model: db.role, include: ['permissions'] }] - }) - } else { - user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.name$': permissionName }, - include: [{ as: 'roles', model: db.role, include: ['permissions'] }] - }) - } - return user !== null -} - -// Get a list of GroupIDs the user has the given permission for. 0 means for all groups. -async function getAllowedGroups (userid, permissionName) { - var superAdmin = await isSuperadmin(userid) - if (superAdmin) return [0] - var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.name$': permissionName }, - include: [{ as: 'roles', model: db.role, include: ['permissions', 'groups'] }] - }) - // User doesn't have the permission - if (user === null) return [] - // User has permission, permission is not groupdependent - else if (!user.roles[0].permissions[0].groupdependent) return [0] - // User has permission, permission is groupdependent - else { - var permGrps = [] - for (let i = 0; i < user.roles.length; i++) { - var whitelist = [] - var blacklist = [] - // Fill in white- and blacklist - for (let j = 0; j < user.roles[i].groups.length; j++) { - if (user.roles[i].groups[j].role_x_group.blacklist) { - blacklist.push(user.roles[i].groups[j]) - } else { - whitelist.push(user.roles[i].groups[j]) - } - } - - // Get childs of white and blacklist groups - var whiteSubChilds = await groupUtil.getAllChildren(whitelist) - var blackSubChilds = await groupUtil.getAllChildren(blacklist) - - // Add all whitelist-ids to result. - permGrps = permGrps.concat(whitelist.map(x => x.id)) - permGrps = permGrps.concat(whiteSubChilds.subgroups.map(s => s.id)) - - // Filter out blacklist-ids from the result. - blacklist = blacklist.map(x => x.id) - blacklist = blacklist.concat(blackSubChilds.subgroups.map(x => x.id)) - for (let k = 0; k < blacklist.length; k++) { - var index = permGrps.indexOf(blacklist[k]) - if (index > -1) { - permGrps.splice(index, 1) - } - } - } - // Filter result for unique entries - return permGrps.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) - } -} - -// Check if the user has a given permission for a given group. -async function hasPermissionForGroup (userid, permissionName, groupId) { - var superAdmin = await isSuperadmin(userid) - if (superAdmin) return true - var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.name$': permissionName }, - include: [{ as: 'roles', model: db.role, include: ['permissions', 'groups'] }] - }) - // User doesn't have permission - if (user === null) return false - // User has permission, permission is not groupdependent - else if (!user.roles[0].permissions[0].groupdependent) return true - // User has permission, permission is groupdependent, check for group - else { - var result = false - var whitelist = [] - var blacklist = [] - // Fill in white- and blacklist - for (let i = 0; i < user.roles.length; i++) { - for (let j = 0; j < user.roles[i].groups.length; j++) { - if (user.roles[i].groups[j].role_x_group.blacklist) { - blacklist.push(user.roles[i].groups[j].id) - } else { - whitelist.push(user.roles[i].groups[j].id) - } - } - } - // Shortcut - if (blacklist.includes(groupId)) { - return false - } - // Remember it was found, check if any parent is in the blacklist tho. - if (whitelist.includes(groupId)) { - result = true - } - // Check parents for white-/blacklist entries. - result = await checkParents(groupId, whitelist, blacklist, result) - return result - } -} - -// Get a list of ClientIDs the user has the given permission for. 0 means for all clients. -async function getAllowedClients (userid, permissionName) { - var superAdmin = await isSuperadmin(userid) - if (superAdmin) return [0] - var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.name$': permissionName }, - include: [{ as: 'roles', model: db.role, include: ['permissions', { as: 'groups', model: db.group, include: ['clients'] }] }] - }) - // User doesn't have the permission - if (user === null) return [] - // User has permission, permission is not groupdependent - else if (!user.roles[0].permissions[0].groupdependent) return [0] - // User has permission, permission is groupdependent - else { - var permClients = [] - for (let i = 0; i < user.roles.length; i++) { - var whitelist = [] - var blacklist = [] - // Fill in white- and blacklist - for (let j = 0; j < user.roles[i].groups.length; j++) { - if (user.roles[i].groups[j].role_x_group.blacklist) { - blacklist.push(user.roles[i].groups[j]) - } else { - whitelist.push(user.roles[i].groups[j]) - } - } - - // Get childs of white and blacklist groups - var whiteSubChilds = await groupUtil.getAllChildren(whitelist) - var blackSubChilds = await groupUtil.getAllChildren(blacklist) - - // Add all whitelist-ids to result. - permClients = permClients.concat(whiteSubChilds.clients.map(s => s.id)) - - // Filter out blacklist-ids from the result. - blackSubChilds = blackSubChilds.clients.map(x => x.id) - for (let k = 0; k < blackSubChilds.length; k++) { - var index = permClients.indexOf(blackSubChilds[k]) - if (index > -1) { - permClients.splice(index, 1) - } - } - } - // Filter result for unique entries - return permClients.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos }) - } -} - -// Check if the user has a given permission for a given client. -async function hasPermissionForClient (userid, permissionName, clientId) { - var superAdmin = await isSuperadmin(userid) - if (superAdmin) return true - var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.name$': permissionName }, - include: [{ as: 'roles', model: db.role, include: ['permissions', { as: 'groups', model: db.group, include: ['clients'] }] }] - }) - // User doesn't have permission - if (user === null) return false - // User has permission, permission is not groupdependent - else if (!user.roles[0].permissions[0].groupdependent) return true - // User has permission, permission is groupdependent, check for client - else { - var result = false - var whitelist = [] - var blacklist = [] - // Fill in white- and blacklist - for (let i = 0; i < user.roles.length; i++) { - for (let j = 0; j < user.roles[i].groups.length; j++) { - var clients = user.roles[i].groups[j].clients.map(c => c.id) - if (user.roles[i].groups[j].role_x_group.blacklist) { - // Shortcut - if (clients.includes(clientId)) return false - blacklist.push(user.roles[i].groups[j].id) - } else { - // Remember it was found, check if any parent is in the blacklist tho. - if (clients.includes(clientId)) result = true - whitelist.push(user.roles[i].groups[j].id) - } - } - } - // Get groups the client is assigned to - var client = await db.client.findOne({ - where: { id: clientId }, - include: [{ as: 'groups', model: db.group }] - }) - var groupIds = client.groups.map(g => g.id) - // Check parents for white-/blacklist entries. - result = await checkParents(groupIds, whitelist, blacklist, result) - return result - } -} - -// Check if parents of groupIds are in the whitelist / blacklist -async function checkParents (groupIds, whitelist, blacklist, result) { - // No whitelist means the group cant be in one - if (whitelist.length === 0) return false - // No blacklist means the result can't be changed once it's true - if (blacklist.length === 0 && result) return true - - var parentIds = [] - var groups = await db.group.findAll({ where: { id: groupIds }, include: ['parents'] }) - for (let i = 0; i < groups.length; i++) { - for (let j = 0; j < groups[i].parents.length; j++) { - var id = groups[i].parents[j].id - // blacklisted - if (blacklist.includes(id)) return false - // Remember, but a further parent can still be blacklisted, so continue. - if (whitelist.includes(id)) result = true - if (!parentIds.includes(id)) parentIds.push(id) - } - } - // No further parents found, result is the result. - if (parentIds.length === 0) return result - // Check next layer of parents - result = await checkParents(parentIds, whitelist, blacklist, result) - return result -} -- cgit v1.2.3-55-g7522