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