summaryrefslogtreecommitdiffstats
path: root/server/lib/permissions
diff options
context:
space:
mode:
authorChristian Hofmaier2019-02-25 04:25:08 +0100
committerChristian Hofmaier2019-02-25 04:25:08 +0100
commit7b098c8b969a1d283a94391d9d8050ad0c5a4d13 (patch)
tree82d9f6edbc4503d3419a41626a986c4797478c8d /server/lib/permissions
parent[webapp/datatable] improved slim mode (diff)
downloadbas-7b098c8b969a1d283a94391d9d8050ad0c5a4d13.tar.gz
bas-7b098c8b969a1d283a94391d9d8050ad0c5a4d13.tar.xz
bas-7b098c8b969a1d283a94391d9d8050ad0c5a4d13.zip
[permissionmanager] rework for blacklist system
- integrate PM into PM itself - wildcard function for hasPermission()
Diffstat (limited to 'server/lib/permissions')
-rw-r--r--server/lib/permissions/permissions.json35
-rw-r--r--server/lib/permissions/permissionutil.js192
2 files changed, 169 insertions, 58 deletions
diff --git a/server/lib/permissions/permissions.json b/server/lib/permissions/permissions.json
index 96c971d..f574367 100644
--- a/server/lib/permissions/permissions.json
+++ b/server/lib/permissions/permissions.json
@@ -1,17 +1,22 @@
[
- {
- "name": "permissions.saverole",
- "descr": "For saving a role",
- "groupdependent": false
- },
- {
- "name": "permissions.editrole",
- "descr": "For editing a role",
- "groupdependent": false
- },
- {
- "name": "permissions.deleterole",
- "descr": "For deleting a role",
- "groupdependent": false
- }
+ {
+ "name": "superadmin",
+ "descr": "Can do anything. Is like superman.",
+ "groupdependent": false
+ },
+ {
+ "name": "permissions.viewrole",
+ "descr": "For viewing the role list.",
+ "groupdependent": false
+ },
+ {
+ "name": "permissions.editrole",
+ "descr": "For save/edit/delete roles.",
+ "groupdependent": false
+ },
+ {
+ "name": "permissions.grantrevoke",
+ "descr": "For grant/revoke roles to/from users.",
+ "groupdependent": false
+ }
] \ No newline at end of file
diff --git a/server/lib/permissions/permissionutil.js b/server/lib/permissions/permissionutil.js
index 709cd29..532af6c 100644
--- a/server/lib/permissions/permissionutil.js
+++ b/server/lib/permissions/permissionutil.js
@@ -14,15 +14,39 @@ function exportFunctions (req, res, next) {
next()
}
-async function hasPermission (userid, permissionName) {
+async function isSuperadmin (userid) {
var user = await db.user.findOne({
- where: { id: userid, '$roles.permissions.name$': permissionName },
+ 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$': { $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'] }]
@@ -35,12 +59,33 @@ async function getAllowedGroups (userid, permissionName) {
else {
var permGrps = []
for (let i = 0; i < user.roles.length; i++) {
- // Add groups of the roles to the result
- permGrps = permGrps.concat(user.roles[i].groups.map(g => g.id))
- if (user.roles[i].recursiveGroups) {
- // The role is flagged recursive, so add child ids to result
- var subChilds = await groupUtil.getAllChildren(user.roles[i].groups)
- permGrps = permGrps.concat(subChilds.subgroups.map(s => s.id))
+ 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
@@ -48,7 +93,10 @@ async function getAllowedGroups (userid, permissionName) {
}
}
+// 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'] }]
@@ -59,19 +107,37 @@ async function hasPermissionForGroup (userid, permissionName, groupId) {
else if (!user.roles[0].permissions[0].groupdependent) return true
// User has permission, permission is groupdependent, check for group
else {
- if (user.roles.map(r => r.groups.map(g => g.id)).includes(groupId)) return true
- var permGrps = []
+ var result = false
+ var whitelist = []
+ var blacklist = []
+ // Fill in white- and blacklist
for (let i = 0; i < user.roles.length; i++) {
- if (user.roles[i].recursiveGroups) permGrps = permGrps.concat(user.roles[i].groups.map(g => g.id))
+ 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
}
- permGrps = permGrps.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos })
- // get all parents of groupId and check if any parentid is in the list of groups of RECURSIVE flagged roles.
- var result = await checkParentsForIds(groupId, permGrps)
+ // 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'] }] }]
@@ -84,13 +150,30 @@ async function getAllowedClients (userid, permissionName) {
else {
var permClients = []
for (let i = 0; i < user.roles.length; i++) {
- if (user.roles[i].recursiveGroups) {
- // The role is flagged recursive, so add clients of childs to result
- var subChilds = await groupUtil.getAllChildren(user.roles[i].groups)
- permClients = permClients.concat(subChilds.clients.map(c => c.id))
- } else {
- for (let j = 0; j < user.roles[i].groups.length; j++) {
- permClients = permClients.concat(user.roles[i].groups[j].clients.map(c => c.id))
+ 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)
}
}
}
@@ -99,49 +182,72 @@ async function getAllowedClients (userid, permissionName) {
}
}
+// 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 permGrps = []
+ 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 groupClients = user.roles[i].groups[j].clients.map(c => c.id)
- if (groupClients.includes(clientId)) return true
+ 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)
+ }
}
- if (user.roles[i].recursiveGroups) permGrps = permGrps.concat(user.roles[i].groups.map(g => g.id))
}
- permGrps = permGrps.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos })
+ // 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)
- var result = await checkParentsForIds(groupIds, permGrps)
+ // Check parents for white-/blacklist entries.
+ result = await checkParents(groupIds, whitelist, blacklist, result)
return result
}
}
-async function checkParentsForIds (groupIds, listOfIds) {
- if (listOfIds.length === 0) return false
- if (groupIds.length === 0) return false
+// 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 = []
- return db.group.findAll({ where: { id: groupIds }, include: ['parents'] }).then(groups => {
- 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
- if (listOfIds.includes(id)) return true
- if (!parentIds.includes(id)) parentIds.push(id)
- }
+ 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)
}
- if (parentIds.length === 0) return false
- return checkParentsForIds(parentIds, listOfIds).then(response => {
- return response
- })
- })
-} \ No newline at end of file
+ }
+ // 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
+}