Skip to content

Commit

Permalink
add validation middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
Dugnist committed Jul 1, 2018
1 parent d73276e commit 2dfcca9
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 27 deletions.
6 changes: 3 additions & 3 deletions ROADMAP.md
Expand Up @@ -16,7 +16,7 @@ This document could be influenced by the community feedback, security issues, st
* ~~ROUTER with routes and middlewares support.~~
* ~~Add "express" REST plugin.~~
* ~~Add <a href="https://github.com/Dugnist/jsberry/blob/master/STORE.md">"mongoose" plugin</a>.~~
* ~~vulnerabilities checkers: "nsp" and "snyk".~~
* ~~Vulnerabilities checkers: "nsp" and "snyk".~~
* ~~Update middlewares, add layers.~~
* ~~Add <a href="https://github.com/Dugnist/jsberry/blob/master/STORE.md">"koa" REST plugin</a>.~~
* ~~Add <a href="https://github.com/Dugnist/jsberry/blob/master/STORE.md">"twillio" sms plugin</a>.~~
Expand All @@ -30,9 +30,9 @@ This document could be influenced by the community feedback, security issues, st
* ~~Add "websockets" plugin~~.
* ~~Add <a href="https://github.com/Dugnist/jsberry/blob/master/STORE.md">"restify" REST plugin</a>.~~
* ~~Overwritten default logger, added "facade" abstraction to use any loggers.~~
* Error handler module.
* Validation middleware.
* ~~Validation middleware using "Joi".~~
* Permission middleware.
* Error handler module.
* Add "sequelize" plugin.
* Add "nginx" and ~~"docker"~~ config.

Expand Down
61 changes: 51 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions package.json
Expand Up @@ -39,18 +39,14 @@
"passport-local": "^1.0.0"
},
"dependencies": {
"body-parser": "^1.18.3",
"chalk": "^2.4.1",
"compression": "^1.7.2",
"cors": "^2.8.4",
"cross-env": "^5.0.5",
"eslint": "^4.4.1",
"eslint-config-google": "^0.8.1",
"express": "^4.16.3",
"express-graphql": "^0.6.12",
"graphql": "^0.13.2",
"helmet": "^3.12.1",
"husky": "^0.14.3",
"joi": "^13.4.0",
"lint-staged": "^7.1.2",
"mongoose": "^5.1.6",
"nodemon": "^1.17.5",
Expand Down
22 changes: 20 additions & 2 deletions src/modules/users/config.json
Expand Up @@ -2,8 +2,26 @@
"name": "routing",
"version": "0.0.2",
"routes": {
"users_auth": { "path": "users/auth", "method": "get" },
"users_get": { "path": "users/get/:id", "method": "get", "middleware": "authMiddleware" }
"users_auth": {
"path": "users/auth",
"method": "get",
"middlewares": ["userValidationMiddleware"],
"validation": {
"path": "users/auth",
"schema": "auth",
"parameters": ["query"]
}
},
"users_get": {
"path": "users/get/:id",
"method": "get",
"middlewares": ["userValidationMiddleware", "authMiddleware"],
"validation": {
"path": "users/get",
"schema": "getUser",
"parameters": ["query", "params"]
}
}
},
"events": {
"users_message": { "name": "users.message" },
Expand Down
1 change: 1 addition & 0 deletions src/modules/users/controller.js
Expand Up @@ -30,6 +30,7 @@ module.exports = (ACTIONS) => ({
*/
getUser: async({ id }) => {
const userOptions = { model: USER.model, payload: { id } };
console.log(userOptions);
const user = await ACTIONS.send('database.read', userOptions);

if (!user) throw new Error(`Incorrect ID: ${id}!`);
Expand Down
10 changes: 4 additions & 6 deletions src/modules/users/index.js
Expand Up @@ -5,6 +5,7 @@ const controller = require('./controller');

// Import user middlewares
const authMiddleware = require('./middlewares/auth.middleware');
const userValidationMiddleware = require('./middlewares/validation.middleware');
const testMiddleware = require('./middlewares/test.middleware');

// Import user graphql schema
Expand Down Expand Up @@ -48,6 +49,7 @@ module.exports = ({ ACTIONS, ROUTER, utils, show }) => {
ROUTER.set('middlewares', { testMiddleware });
ROUTER.set('middlewares', {
authMiddleware: authMiddleware(ACTIONS),
userValidationMiddleware: userValidationMiddleware(ACTIONS),
}, 'routes');

/**
Expand All @@ -64,10 +66,7 @@ module.exports = ({ ACTIONS, ROUTER, utils, show }) => {
ACTIONS.on(users_auth, async({ headers, query, body, params }) => {
try {
const { login, password, email } = query;

if (!login || !password) throw new Error('Missing login or password!');

const userData = { login, password, email }; // ToDo: validation mwr
const userData = { login, password, email };
const user = await userController.authorization(userData);

return user.toAuthKeys();
Expand All @@ -92,8 +91,7 @@ module.exports = ({ ACTIONS, ROUTER, utils, show }) => {
try {
const { id } = params;

if (!id) throw new Error('Missing id value!');
if (auth.id === id) return user.toAuthKeys();
if ((auth || {}).id === id) return user.toAuthKeys();

const user = await userController.getUser({ id });

Expand Down
30 changes: 30 additions & 0 deletions src/modules/users/middlewares/validation.middleware.js
@@ -0,0 +1,30 @@
/*
* JsBerry example: validation middleware
*/

const { routes } = require('../config.json');
const validation = require('../validation-schemas');

module.exports = (ACTIONS) => async(req, res, next) => {
try {
// Find route with searched validation
const currentRoute = Object.values(routes).find((r) =>
req.url.indexOf(r.validation.path) !== -1 && // compare url's
(req.method || '').toLowerCase() === r.method); // compare methods

// Combine (query | body | params) parameters by config values from request
const parameters = (currentRoute.validation.parameters || [])
.map((type) => req[type]).reduce((prev, next) => ({ ...prev, ...next }));

// Get validation schema by name from config
const result = validation[currentRoute.validation.schema](parameters);

if (result.error && result.error.message) {
throw new Error(result.error.message);
}

next();
} catch (error) {
res.send({ error: 400, message: error.message });
}
};
12 changes: 12 additions & 0 deletions src/modules/users/validation-schemas/auth.js
@@ -0,0 +1,12 @@
const Joi = require('joi');

const schema = Joi.object().keys({
login: Joi.string().alphanum().min(4).max(30).required(),
password: Joi.string().regex(/^[a-zA-Z0-9_\-]{6,30}$/g).required()
.error(() => `'password' must be at least 6 characters long and must
contain at least one lower case letter, one upper case letter, one number
and one symbol character [_-]`),
email: Joi.string().email().min(6).max(30).required(),
});

module.exports = (payload) => Joi.validate(payload, schema);
7 changes: 7 additions & 0 deletions src/modules/users/validation-schemas/getUser.js
@@ -0,0 +1,7 @@
const Joi = require('joi');

const schema = Joi.object().keys({
id: Joi.string().regex(/^[a-zA-Z0-9_]{6,30}$/).required(),
});

module.exports = (payload) => Joi.validate(payload, schema);
7 changes: 7 additions & 0 deletions src/modules/users/validation-schemas/index.js
@@ -0,0 +1,7 @@
const auth = require('./auth');
const getUser = require('./getUser');

module.exports = {
auth,
getUser,
};
3 changes: 2 additions & 1 deletion src/plugins/express_api/index.js
Expand Up @@ -87,7 +87,8 @@ module.exports = ({ ACTIONS, ROUTER, show }) => {

for (let _route in allRoutes) {
const route = allRoutes[_route];
const mw = allMiddlewares[route.middleware] || ((rq, rs, next) => next());
const mw = (route.middlewares || [])
.map((mwName) => allMiddlewares[mwName]);

app[route.method](`/${route.path}`, mw, (req, res, next) => {
const { headers, query, body, params, auth } = req;
Expand Down

0 comments on commit 2dfcca9

Please sign in to comment.