From d6e07668fb381d1c0ec8ba815b4ffab979994bc9 Mon Sep 17 00:00:00 2001 From: Christian Hofmaier Date: Mon, 4 Feb 2019 00:03:45 +0000 Subject: Implement Middlware for Permission Manager --- server/api/permissions.js | 15 +++--- server/api/users.js | 5 +- server/lib/authentication.js | 3 ++ server/lib/permissions/permissions.json | 16 +++--- server/lib/permissions/permissionutil.js | 83 ++++++++++++++++++-------------- server/router.js | 3 +- 6 files changed, 68 insertions(+), 57 deletions(-) (limited to 'server') diff --git a/server/api/permissions.js b/server/api/permissions.js index 2e1d5bf..7e2573c 100644 --- a/server/api/permissions.js +++ b/server/api/permissions.js @@ -2,14 +2,15 @@ var path = require('path') var db = require(path.join(__appdir, 'lib', 'sequelize')) var express = require('express') -var noAuthRouter = express.Router() +const { decorateApp } = require('@awaitjs/express') +var router = decorateApp(express.Router()) /* * ?id= * * @return: Returns the information about a role and it's permissions and groups. */ -noAuthRouter.get('/getRoleById/:id', (req, res) => { +router.get('/getRoleById/:id', (req, res) => { db.role.findOne({ where: { id: req.params.id }, include: ['permissions', 'groups'] }).then(role => { if (role) res.send(role) else res.status(404).end() @@ -19,7 +20,7 @@ noAuthRouter.get('/getRoleById/:id', (req, res) => { /* * @return: Returns a list of all roles in the database. */ -noAuthRouter.get('/getRoleList', (req, res) => { +router.get('/getRoleList', (req, res) => { db.role.findAll({ attributes: ['id', 'name', 'descr'] }).then(function (roles) { @@ -30,7 +31,7 @@ noAuthRouter.get('/getRoleList', (req, res) => { /* * @return: Returns a list of all permissions in the database. */ -noAuthRouter.get('/getPermissionList', (req, res) => { +router.get('/getPermissionList', (req, res) => { db.permission.findAll().then(function (permissions) { res.status(200).send(permissions) }) @@ -41,7 +42,7 @@ noAuthRouter.get('/getPermissionList', (req, res) => { * * Deletes the role to the given id. */ -noAuthRouter.post('/deleteRoles', (req, res) => { +router.post('/deleteRoles', (req, res) => { const roleIds = req.body.id db.role.destroy({ where: { id: roleIds } }).then(function () { res.status(200).send('success') @@ -58,7 +59,7 @@ noAuthRouter.post('/deleteRoles', (req, res) => { * * Creates or updates a role. If recursiveMode is set to true, the are saved with childs. */ -noAuthRouter.post('/saveRole', (req, res) => { +router.post('/saveRole', (req, res) => { const role = req.body if (role.id === 0) { // Insert new role in the db. @@ -80,4 +81,4 @@ noAuthRouter.post('/saveRole', (req, res) => { } }) -module.exports.noAuthRouter = noAuthRouter +module.exports.router = router diff --git a/server/api/users.js b/server/api/users.js index 35da1db..3caf4c8 100644 --- a/server/api/users.js +++ b/server/api/users.js @@ -7,10 +7,7 @@ var jwt = require('jsonwebtoken') module.exports.get = { getUserInfo: function (req, res) { - var decodedToken = jwt.decode(req.token, { complete: true }) - var userId = decodedToken.payload.user.id - - db.user.findOne({ where: { id: userId } }).then(userDb => { + db.user.findOne({ where: { id: req.user.id } }).then(userDb => { var user = { } user.id = userDb.id user.username = userDb.username diff --git a/server/lib/authentication.js b/server/lib/authentication.js index 0681011..58d5e10 100644 --- a/server/lib/authentication.js +++ b/server/lib/authentication.js @@ -102,6 +102,9 @@ module.exports = { else return next(new Error('TOKEN_INVALID')) } req.token = token + const decodedToken = jwt.decode(token, { complete: true }) + req.user = { id: decodedToken.payload.user.id } + next() }) } diff --git a/server/lib/permissions/permissions.json b/server/lib/permissions/permissions.json index cdb9773..96c971d 100644 --- a/server/lib/permissions/permissions.json +++ b/server/lib/permissions/permissions.json @@ -1,17 +1,17 @@ [ { - "name": "A", - "descr": "Testing permission A", - "groupdependent": true + "name": "permissions.saverole", + "descr": "For saving a role", + "groupdependent": false }, { - "name": "Very long permission name with very long description", - "descr": "Even longer description of the very long permission with the very long name with the very long description", + "name": "permissions.editrole", + "descr": "For editing a role", "groupdependent": false }, { - "name": "Short is short", - "descr": "nanananana", - "groupdependent": true + "name": "permissions.deleterole", + "descr": "For deleting a role", + "groupdependent": false } ] \ No newline at end of file diff --git a/server/lib/permissions/permissionutil.js b/server/lib/permissions/permissionutil.js index fee2181..709cd29 100644 --- a/server/lib/permissions/permissionutil.js +++ b/server/lib/permissions/permissionutil.js @@ -3,19 +3,28 @@ const path = require('path') var db = require(path.join(__appdir, 'lib', 'sequelize')) var groupUtil = require(path.join(__appdir, 'lib', 'grouputil')) -module.exports = { hasPermission, getAllowedGroups, hasPermissionForGroup, getAllowedClients, hasPermissionForClient } +module.exports = { exportFunctions } -async function hasPermission (userid, permissionid) { +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 hasPermission (userid, permissionName) { var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.id$': permissionid }, + where: { id: userid, '$roles.permissions.name$': permissionName }, include: [{ as: 'roles', model: db.role, include: ['permissions'] }] }) return user !== null } -async function getAllowedGroups (userid, permissionid) { +async function getAllowedGroups (userid, permissionName) { var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.id$': permissionid }, + where: { id: userid, '$roles.permissions.name$': permissionName }, include: [{ as: 'roles', model: db.role, include: ['permissions', 'groups'] }] }) // User doesn't have the permission @@ -39,9 +48,9 @@ async function getAllowedGroups (userid, permissionid) { } } -async function hasPermissionForGroup (userid, permissionid, groupid) { +async function hasPermissionForGroup (userid, permissionName, groupId) { var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.id$': permissionid }, + where: { id: userid, '$roles.permissions.name$': permissionName }, include: [{ as: 'roles', model: db.role, include: ['permissions', 'groups'] }] }) // User doesn't have permission @@ -50,41 +59,21 @@ async function hasPermissionForGroup (userid, permissionid, 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 + if (user.roles.map(r => r.groups.map(g => g.id)).includes(groupId)) return true var permGrps = [] 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)) } 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) + var result = await checkParentsForIds(groupId, permGrps) return result } } -async function checkParentsForIds (groupIds, listOfIds) { - if (listOfIds.length === 0) return false - if (groupIds.length === 0) return false - - 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) - } - } - if (parentIds.length === 0) return false - return checkParentsForIds(parentIds, listOfIds).then(response => { - return response - }) - }) -} - -async function getAllowedClients (userid, permissionid) { +async function getAllowedClients (userid, permissionName) { var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.id$': permissionid }, + 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 @@ -110,9 +99,9 @@ async function getAllowedClients (userid, permissionid) { } } -async function hasPermissionForClient (userid, permissionid, clientid) { +async function hasPermissionForClient (userid, permissionName, clientId) { var user = await db.user.findOne({ - where: { id: userid, '$roles.permissions.id$': permissionid }, + where: { id: userid, '$roles.permissions.name$': permissionName }, include: [{ as: 'roles', model: db.role, include: ['permissions', { as: 'groups', model: db.group, include: ['clients'] }] }] }) if (user === null) return false @@ -122,17 +111,37 @@ async function hasPermissionForClient (userid, permissionid, clientid) { 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 + if (groupClients.includes(clientId)) return true } 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 }) var client = await db.client.findOne({ - where: { id: clientid }, + where: { id: clientId }, include: [{ as: 'groups', model: db.group }] }) - var groupids = client.groups.map(g => g.id) - var result = await checkParentsForIds(groupids, permGrps) + var groupIds = client.groups.map(g => g.id) + var result = await checkParentsForIds(groupIds, permGrps) return result } } + +async function checkParentsForIds (groupIds, listOfIds) { + if (listOfIds.length === 0) return false + if (groupIds.length === 0) return false + + 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) + } + } + if (parentIds.length === 0) return false + return checkParentsForIds(parentIds, listOfIds).then(response => { + return response + }) + }) +} \ No newline at end of file diff --git a/server/router.js b/server/router.js index 6070f33..1eadc48 100644 --- a/server/router.js +++ b/server/router.js @@ -2,6 +2,7 @@ var express = require('express') var router = express.Router() var path = require('path') var fs = require('fs') +var permUtil = require(path.join(__dirname, 'lib', 'permissions', 'permissionutil')) // Authentication routes var auth = require(path.join(__dirname, 'lib', 'authentication')) @@ -17,7 +18,7 @@ fs.readdirSync(path.join(__dirname, 'api')).forEach(filename => { // Public callable functions. if (api.noAuthRouter) router.use('/' + filename.split('.')[0] + '/', api.noAuthRouter) // Authentication needed - if (api.router) router.use('/' + filename.split('.')[0] + '/', auth.verifyToken, api.router) + if (api.router) router.use('/' + filename.split('.')[0] + '/', auth.verifyToken, permUtil.exportFunctions, api.router) }) // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -- cgit v1.2.3-55-g7522