Add permission level checks

pull/1/head
Florian Hartwich 2017-06-08 13:14:53 +02:00
parent a215d41ec3
commit 9b8bcd0722
10 changed files with 57 additions and 27 deletions

View File

@ -2,6 +2,7 @@
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
const config = require('../config/config'); const config = require('../config/config');
const AppUser = require('../models/app-user');
const apiAuthentication = (req, res, next) => { const apiAuthentication = (req, res, next) => {
@ -18,7 +19,16 @@ const apiAuthentication = (req, res, next) => {
} else { } else {
// if everything is good, save to request for use in other routes // if everything is good, save to request for use in other routes
req.decoded = decoded; req.decoded = decoded;
next(); AppUser.findById(decoded.sub, (err, item) => {
if (err) {
return res.status(403).send({
success: false,
message: 'token is not associated to any actual user'
});
}
req.user = item;
next();
});
} }
}); });

View File

@ -0,0 +1,20 @@
"use strict";
let check = (requiredPermission, actualPermission, res, next) => {
if (actualPermission >= requiredPermission) {
return next();
}
return res.status(403).send({
success: false,
message: 'permission denied'
});
};
module.exports = {
checkSql: (req, res, next) => { check(1, req.user.permission, res, next) },
checkHl: (req, res, next) => { check(2, req.user.permission, res, next) },
checkMT: (req, res, next) => { check(3, req.user.permission, res, next) },
checkAdmin: (req, res, next) => { check(4, req.user.permission, res, next) }
};

View File

@ -1,4 +1,4 @@
"use strict" "use strict";
const sortCollectionBy = (collection, key) => { const sortCollectionBy = (collection, key) => {
collection.sort((a, b) => { collection.sort((a, b) => {

View File

@ -18,7 +18,7 @@ const AppUserSchema = new Schema({
get: v => Math.round(v), get: v => Math.round(v),
set: v => Math.round(v), set: v => Math.round(v),
min: 0, min: 0,
max: 3, max: 4,
default: 0 default: 0
} }
}, { }, {

View File

@ -12,6 +12,7 @@ const logger = require('debug')('cc:decorations');
const codes = require('./http-codes'); const codes = require('./http-codes');
const apiAuthenticationMiddleware = require('../middleware/auth-middleware'); const apiAuthenticationMiddleware = require('../middleware/auth-middleware');
const checkHl = require('../middleware/permission-check').checkHl;
const routerHandling = require('../middleware/router-handling'); const routerHandling = require('../middleware/router-handling');
// Mongoose Model using mongoDB // Mongoose Model using mongoDB
@ -46,7 +47,7 @@ decoration.route('/')
}); });
}) })
.post(apiAuthenticationMiddleware, upload.single('image'), (req, res, next) => { .post(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
const decoration = new DecorationModel(req.body); const decoration = new DecorationModel(req.body);
// timestamp and default are set automatically by Mongoose Schema Validation // timestamp and default are set automatically by Mongoose Schema Validation
decoration.save((err) => { decoration.save((err) => {
@ -86,7 +87,7 @@ decoration.route('/:id')
}); });
}) })
.patch(apiAuthenticationMiddleware, upload.single('image'), (req, res, next) => { .patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
if (!req.body || (req.body._id && req.body._id !== req.params.id)) { if (!req.body || (req.body._id && req.body._id !== req.params.id)) {
// little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match // little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match
const err = new Error('id of PATCH resource and send JSON body are not equal ' + req.params.id + " " + req.body._id); const err = new Error('id of PATCH resource and send JSON body are not equal ' + req.params.id + " " + req.body._id);
@ -125,7 +126,7 @@ decoration.route('/:id')
}) })
}) })
.delete(apiAuthenticationMiddleware, (req, res, next) => { .delete(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
DecorationModel.findByIdAndRemove(req.params.id, (err, item) => { DecorationModel.findByIdAndRemove(req.params.id, (err, item) => {
if (err) { if (err) {
err.status = codes.wrongrequest; err.status = codes.wrongrequest;

View File

@ -12,6 +12,7 @@ const logger = require('debug')('cc:ranks');
const codes = require('./http-codes'); const codes = require('./http-codes');
const apiAuthenticationMiddleware = require('../middleware/auth-middleware'); const apiAuthenticationMiddleware = require('../middleware/auth-middleware');
const checkHl = require('../middleware/permission-check').checkHl;
const routerHandling = require('../middleware/router-handling'); const routerHandling = require('../middleware/router-handling');
// Mongoose Model using mongoDB // Mongoose Model using mongoDB
@ -49,7 +50,7 @@ ranks.route('/')
}); });
}) })
.post(apiAuthenticationMiddleware, upload.single('image'), (req, res, next) => { .post(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
const rank = new RankModel(req.body); const rank = new RankModel(req.body);
// timestamp and default are set automatically by Mongoose Schema Validation // timestamp and default are set automatically by Mongoose Schema Validation
rank.save((err) => { rank.save((err) => {
@ -89,7 +90,7 @@ ranks.route('/:id')
}); });
}) })
.patch(apiAuthenticationMiddleware, upload.single('image'), (req, res, next) => { .patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
if (!req.body || (req.body._id && req.body._id !== req.params.id)) { if (!req.body || (req.body._id && req.body._id !== req.params.id)) {
// little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match // little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match
@ -130,7 +131,7 @@ ranks.route('/:id')
}) })
}) })
.delete(apiAuthenticationMiddleware, (req, res, next) => { .delete(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
RankModel.findByIdAndRemove(req.params.id, (err, item) => { RankModel.findByIdAndRemove(req.params.id, (err, item) => {
if (err) { if (err) {
err.status = codes.wrongrequest; err.status = codes.wrongrequest;

View File

@ -12,6 +12,7 @@ const logger = require('debug')('cc:squads');
const codes = require('./http-codes'); const codes = require('./http-codes');
const apiAuthenticationMiddleware = require('../middleware/auth-middleware'); const apiAuthenticationMiddleware = require('../middleware/auth-middleware');
const checkHl = require('../middleware/permission-check').checkHl;
const routerHandling = require('../middleware/router-handling'); const routerHandling = require('../middleware/router-handling');
// Mongoose Model using mongoDB // Mongoose Model using mongoDB
@ -44,7 +45,7 @@ squads.route('/')
}); });
}) })
.post(apiAuthenticationMiddleware, upload.single('image'), (req, res, next) => { .post(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
const squad = new SquadModel(req.body); const squad = new SquadModel(req.body);
// timestamp and default are set automatically by Mongoose Schema Validation // timestamp and default are set automatically by Mongoose Schema Validation
if (req.file) { if (req.file) {
@ -89,7 +90,7 @@ squads.route('/:id')
}); });
}) })
.patch(apiAuthenticationMiddleware, upload.single('image'), (req, res, next) => { .patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
if (!req.body || (req.body._id && req.body._id !== req.params.id)) { if (!req.body || (req.body._id && req.body._id !== req.params.id)) {
// little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match // little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match
@ -129,7 +130,7 @@ squads.route('/:id')
}) })
}) })
.delete(apiAuthenticationMiddleware, (req, res, next) => { .delete(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
SquadModel.findByIdAndRemove(req.params.id, (err, item) => { SquadModel.findByIdAndRemove(req.params.id, (err, item) => {
if (err) { if (err) {
err.status = codes.wrongrequest; err.status = codes.wrongrequest;

View File

@ -9,6 +9,7 @@ const logger = require('debug')('me2u5:users');
const codes = require('./http-codes'); const codes = require('./http-codes');
const apiAuthenticationMiddleware = require('../middleware/auth-middleware'); const apiAuthenticationMiddleware = require('../middleware/auth-middleware');
const checkHl = require('../middleware/permission-check').checkHl;
const sortCollectionBy = require('../middleware/util').sortCollection; const sortCollectionBy = require('../middleware/util').sortCollection;
const routerHandling = require('../middleware/router-handling'); const routerHandling = require('../middleware/router-handling');
@ -84,7 +85,7 @@ users.route('/')
} }
}) })
.post(apiAuthenticationMiddleware, (req, res, next) => { .post(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
const user = new UserModel(req.body); const user = new UserModel(req.body);
// timestamp and default are set automatically by Mongoose Schema Validation // timestamp and default are set automatically by Mongoose Schema Validation
user.save((err) => { user.save((err) => {
@ -129,7 +130,7 @@ users.route('/:id')
}); });
}) })
.patch(apiAuthenticationMiddleware, (req, res, next) => { .patch(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
if (!req.body || (req.body._id && req.body._id !== req.params.id)) { if (!req.body || (req.body._id && req.body._id !== req.params.id)) {
// little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match // little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match
const err = new Error('id of PATCH resource and send JSON body are not equal ' + req.params.id + " " + req.body._id); const err = new Error('id of PATCH resource and send JSON body are not equal ' + req.params.id + " " + req.body._id);
@ -176,7 +177,7 @@ users.route('/:id')
}) })
}) })
.put(apiAuthenticationMiddleware, (req, res, next) => { .put(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
// first check that the given element id is the same as the URL id // first check that the given element id is the same as the URL id
if (!req.body || req.body._id !== req.params.id) { if (!req.body || req.body._id !== req.params.id) {
// the URL does not fit the given element // the URL does not fit the given element
@ -231,7 +232,7 @@ users.route('/:id')
}) })
}) })
.delete(apiAuthenticationMiddleware, (req, res, next) => { .delete(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
UserModel.findByIdAndRemove(req.params.id, (err, item) => { UserModel.findByIdAndRemove(req.params.id, (err, item) => {
if (err) { if (err) {
err.status = codes.wrongrequest; err.status = codes.wrongrequest;

View File

@ -15,6 +15,8 @@ const urls = require('./config/api-url');
const restAPIchecks = require('./middleware/request-checks.js'); const restAPIchecks = require('./middleware/request-checks.js');
const errorResponseWare = require('./middleware/error-response'); const errorResponseWare = require('./middleware/error-response');
const apiAuthenticationMiddleware = require('./middleware/auth-middleware'); const apiAuthenticationMiddleware = require('./middleware/auth-middleware');
const checkHl = require('./middleware/permission-check').checkHl;
const checkAdmin = require('./middleware/permission-check').checkAdmin;
const signatureCronJob = require('./cron-job/update-signatures'); const signatureCronJob = require('./cron-job/update-signatures');
// router modules // router modules
@ -54,7 +56,7 @@ app.use(restAPIchecks);
// Routes ****************************************************** // Routes ******************************************************
app.use(urls.signatures, signatureRouter); app.use(urls.signatures, signatureRouter);
// initialize logging here to exclude /signature requests // initialize logging at this point to exclude /signature requests
if (process.env.NODE_ENV === config.dev.env) { if (process.env.NODE_ENV === config.dev.env) {
// development logging // development logging
app.use(requestLogger('dev')); app.use(requestLogger('dev'));
@ -69,8 +71,8 @@ app.use(urls.users, userRouter);
app.use(urls.squads, squadRouter); app.use(urls.squads, squadRouter);
app.use(urls.ranks, rankRouter); app.use(urls.ranks, rankRouter);
app.use(urls.decorations, decorationRouter); app.use(urls.decorations, decorationRouter);
app.use(urls.awards, apiAuthenticationMiddleware, awardingRouter); app.use(urls.awards, apiAuthenticationMiddleware, checkHl, awardingRouter);
app.use(urls.command, apiAuthenticationMiddleware, commandRouter); app.use(urls.command, apiAuthenticationMiddleware, checkAdmin, commandRouter);
// send index.html on all different paths // send index.html on all different paths
app.use(function (req, res) { app.use(function (req, res) {
@ -105,13 +107,6 @@ if (process.env.NODE_ENV !== config.test.env) {
}); });
} else { } else {
mongoose.connect(config.database.uri + config.test.db); mongoose.connect(config.database.uri + config.test.db);
for (let collection in mongoose.connection.collections) {
mongoose.connection.collections[collection].drop(function (err) {
if (err) {
console.log('Error while test-Db clean up: ' + err);
}
});
}
app.listen(config.test.port); app.listen(config.test.port);
console.log('Listening on port ' + config.test.port); console.log('Listening on port ' + config.test.port);
} }

View File

@ -51,7 +51,8 @@ describe('Users', () => {
before(function (done) { before(function (done) {
let appUser = { let appUser = {
username: 'testUsr', username: 'testUsr',
password: '$2a$10$i9cBC06uGJnnrqQCh8COkuZLMChLQqw5j4K0yfDQn1udTDAompHka' password: '$2a$10$i9cBC06uGJnnrqQCh8COkuZLMChLQqw5j4K0yfDQn1udTDAompHka',
permission: 2
}; };
let appUserEncoded = { let appUserEncoded = {
username: appUser.username, username: appUser.username,