mirror of
https://github.com/Foltik/Shimapan
synced 2025-01-05 15:58:03 -05:00
Separate middleware from verifyBody logic into bodyVerifier
This commit is contained in:
parent
67909552dc
commit
827072212d
@ -11,7 +11,7 @@ const passport = require('passport');
|
||||
const canonicalizeRequest = require('../../util/canonicalize').canonicalizeRequest;
|
||||
const requireAuth = require('../../util/auth').requireAuth;
|
||||
const wrap = require('../../util/wrap.js');
|
||||
const verifyBody = require('../../util/verifyBody');
|
||||
const bodyVerifier = require('../../util/verifyBody').bodyVerifier;
|
||||
|
||||
// Wraps passport.authenticate to return a promise
|
||||
const authenticate = (req, res, next) => {
|
||||
@ -68,7 +68,7 @@ const registerProps = [
|
||||
{name: 'password', type: 'string'},
|
||||
{name: 'invite', type: 'string'}];
|
||||
router.post('/register',
|
||||
verifyBody(registerProps), canonicalizeRequest,
|
||||
bodyVerifier(registerProps), canonicalizeRequest,
|
||||
validateInvite, validateUsername,
|
||||
wrap(async (req, res, next) => {
|
||||
// Update the database
|
||||
@ -89,7 +89,7 @@ const loginProps = [
|
||||
{name: 'username', type: 'string', optional: true},
|
||||
{name: 'displayname', type: 'string', optional: true},
|
||||
{name: 'password', type: 'string'}];
|
||||
router.post('/login', verifyBody(loginProps), canonicalizeRequest, wrap(async (req, res, next) => {
|
||||
router.post('/login', bodyVerifier(loginProps), canonicalizeRequest, wrap(async (req, res, next) => {
|
||||
// Authenticate
|
||||
const user = await authenticate(req, res, next);
|
||||
if (!user)
|
||||
|
@ -9,13 +9,12 @@ const User = require(ModelPath + 'User.js');
|
||||
const wrap = require('../../util/wrap.js');
|
||||
const requireAuth = require('../../util/auth').requireAuth;
|
||||
const verifyScope = require('../../util/verifyScope');
|
||||
const verifyBody = require('../../util/verifyBody');
|
||||
const bodyVerifier = require('../../util/verifyBody').bodyVerifier;
|
||||
|
||||
const createParams = [{name: 'scope', instance: Array}];
|
||||
router.post('/create', requireAuth('invite.create'), verifyBody(createParams), wrap(async (req, res, next) => {
|
||||
router.post('/create', requireAuth('invite.create'), bodyVerifier(createParams), wrap(async (req, res, next) => {
|
||||
const scope = req.body.scope;
|
||||
const hasPermission = scope.every(scope => verifyScope(req.scope, scope));
|
||||
if (!hasPermission)
|
||||
if (!scope.every(scope => verifyScope(req.scope, scope)))
|
||||
return res.status(403).json({message: 'Requested scope exceeds own scope.'});
|
||||
|
||||
const invite = {
|
||||
@ -38,7 +37,7 @@ router.post('/create', requireAuth('invite.create'), verifyBody(createParams), w
|
||||
}));
|
||||
|
||||
const deleteParams = [{name: 'code', type: 'string'}];
|
||||
router.post('/delete', requireAuth('invite.delete'), verifyBody(deleteParams), wrap(async (req, res, next) => {
|
||||
router.post('/delete', requireAuth('invite.delete'), bodyVerifier(deleteParams), wrap(async (req, res, next) => {
|
||||
let query = {code: req.body.code};
|
||||
|
||||
// Users need a permission to delete invites other than their own
|
||||
@ -48,7 +47,7 @@ router.post('/delete', requireAuth('invite.delete'), verifyBody(deleteParams), w
|
||||
// Find the invite
|
||||
const invite = await Invite.findOne(query).catch(next);
|
||||
if (!invite)
|
||||
return res.status(404).json({message: 'Invite not found.'});
|
||||
return res.status(422).json({message: 'Invite not found.'});
|
||||
|
||||
// Users need a permission to delete invites that have been used
|
||||
if (!verifyScope(req.scope, 'invite.delete.used') && invite.used != null && invite.recipient != null)
|
||||
@ -58,13 +57,15 @@ router.post('/delete', requireAuth('invite.delete'), verifyBody(deleteParams), w
|
||||
res.status(200).json({message: 'Invite deleted.'});
|
||||
}));
|
||||
|
||||
const getParams = [{name: 'code', type: 'string', optional: true}];
|
||||
router.get('/get', requireAuth('invite.get'), verifyBody(getParams), wrap(async (req, res, next) => {
|
||||
const getParams = [{name: 'code', type: 'string', optional: true}, {name: 'issuer', type: 'string', optional: true}];
|
||||
router.get('/get', requireAuth('invite.get'), bodyVerifier(getParams), wrap(async (req, res, next) => {
|
||||
let query = {};
|
||||
|
||||
// Users need a permission to list invites other than their own
|
||||
if (!verifyScope(req.scope, 'invite.get.others'))
|
||||
query.issuer = req.username;
|
||||
else if (req.body.issuer)
|
||||
query.issuer = req.body.issuer;
|
||||
|
||||
// Narrow down the query by code if specified
|
||||
if (req.body.code)
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Verifies a single property is well formed
|
||||
const verifyProp = (req, expected) => new Promise((resolve, reject) => {
|
||||
const prop = req.body[expected.name];
|
||||
const sanitizer = require('sanitizer');
|
||||
|
||||
// Verifies a single property is well formed
|
||||
const verifyProp = (prop, expected) => new Promise((resolve, reject) => {
|
||||
if (!expected.optional && !prop)
|
||||
return reject({code: 400, message: expected.name + ' not specified.'});
|
||||
|
||||
@ -12,13 +12,13 @@ const verifyProp = (req, expected) => new Promise((resolve, reject) => {
|
||||
return reject({code: 400, message: expected.name + ' malformed.'});
|
||||
|
||||
if (prop && expected.maxLength && prop.length > expected.maxLength)
|
||||
return reject({code: 422, message: expected.name + ' too long.'});
|
||||
return reject({code: 400, message: expected.name + ' too long.'});
|
||||
|
||||
if (prop && expected.sanitize && req.sanitize(prop) !== prop)
|
||||
return reject({code: 422, message: expected.name + ' contains invalid characters.'});
|
||||
if (prop && expected.sanitize && sanitizer.sanitize(prop) !== prop)
|
||||
return reject({code: 400, message: expected.name + ' contains invalid characters.'});
|
||||
|
||||
if (prop && expected.restrict && prop.replace(expected.restrict, '') !== prop)
|
||||
return reject({code: 422, message: expected.name + ' contains invalid characters.'});
|
||||
return reject({code: 400, message: expected.name + ' contains invalid characters.'});
|
||||
|
||||
resolve();
|
||||
});
|
||||
@ -26,11 +26,15 @@ const verifyProp = (req, expected) => new Promise((resolve, reject) => {
|
||||
// Verifies the entire request body is well formed
|
||||
// expectedProps follows the format:
|
||||
// [{name: 'myList', instance: 'Array'}, {name: 'myVar', type: 'string', optional: true}, etc.]
|
||||
const verifyBody = expectedProps =>
|
||||
const verifyBody = (body, expectedProps) =>
|
||||
Promise.all(expectedProps.map(expected => verifyProp(body[expected.name], expected)));
|
||||
|
||||
const bodyVerifier = expectedProps =>
|
||||
(req, res, next) => {
|
||||
Promise.all(expectedProps.map(expected => verifyProp(req, expected)))
|
||||
verifyBody(req.body, expectedProps)
|
||||
.then(() => next())
|
||||
.catch(err => res.status(err.code).json({message: err.message}));
|
||||
};
|
||||
|
||||
module.exports = verifyBody;
|
||||
exports.verifyBody = verifyBody;
|
||||
exports.bodyVerifier = bodyVerifier;
|
2309
package-lock.json
generated
2309
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@
|
||||
"passport": "^0.4.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"passport-local-mongoose": "^5.0.1",
|
||||
"sanitizer": "^0.1.3",
|
||||
"type-is": "^1.6.16",
|
||||
"vinyl-source-stream": "^2.0.0"
|
||||
},
|
||||
@ -42,7 +43,8 @@
|
||||
"minimatch": "^3.0.4",
|
||||
"mocha": "^5.2.0",
|
||||
"nodemon": "^1.18.3",
|
||||
"npx": "^10.2.0"
|
||||
"npx": "^10.2.0",
|
||||
"nyc": "^12.0.2"
|
||||
},
|
||||
"author": "Jack Foltz",
|
||||
"license": "LICENSE",
|
||||
|
Loading…
Reference in New Issue
Block a user