summaryrefslogtreecommitdiffstats
path: root/server/lib/permissions/permissionhelper.js
diff options
context:
space:
mode:
authorUdo Walter2019-04-15 17:04:50 +0200
committerUdo Walter2019-04-15 17:04:50 +0200
commit9ff998a5b185c80aa31c57836f9d86b75dcadd6f (patch)
tree765f50d2adc23819b44777af4ee256c10285fd3a /server/lib/permissions/permissionhelper.js
parent[server] grouputils -> grouphelper (diff)
downloadbas-9ff998a5b185c80aa31c57836f9d86b75dcadd6f.tar.gz
bas-9ff998a5b185c80aa31c57836f9d86b75dcadd6f.tar.xz
bas-9ff998a5b185c80aa31c57836f9d86b75dcadd6f.zip
server crash hotfix
Diffstat (limited to 'server/lib/permissions/permissionhelper.js')
-rw-r--r--server/lib/permissions/permissionhelper.js253
1 files changed, 253 insertions, 0 deletions
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
+}