Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const fs = require('fs');
- var jwt = require('jsonwebtoken');
- const File = require(`${__dirlibs}/File`);
- const _ = require('lodash');
- // ----------------------------------------------------------------------------------------------------------
- var controllers = {}
- var routesList = {}
- // ----------------------------------------------------------------------------------------------------------
- function loadControllersAndRoutes() {
- fs.readdirSync(`${__dircontrollers}/rest`).forEach(file => {
- let controllerName = file.split('.')[0];
- controllers[controllerName] = new (require(`${__dircontrollers}/rest/${file}`))(controllerName);
- });
- fs.readdirSync(`${__dirapp}/routes`).forEach(file => {
- let routeName = file.split('.')[0];
- routesList[routeName] = require(`${__dirapp}/routes/${file}`);
- });
- }
- // ----------------------------------------------------------------------------------------------------------
- class Router {
- constructor() {
- if(!Object.keys(controllers).length)
- loadControllersAndRoutes();
- return (req, res, next) => {
- if(req.method == 'OPTIONS') return res.status(200);
- res.success = (data) => { res.status(200).send({status: 200, data: data}).end() };
- res.accessDenied = (data) => { res.status(403).send({status: 403, data: data}).end() };
- res.notFound = (data) => { res.status(404).send({status: 404}).end() };
- res.error = (data) => { LOGGER.error(JSON.stringify(data)); res.status(400).send({status: 400, data: data}).end() };
- res.answer = ({status: status, data: data}) => { res.status(status).send(data) };
- this.setHeaders(req, res);
- this.handleRequest(req, res);
- }
- }
- setHeaders(req, res) {
- res.setHeader('Access-Control-Allow-Origin', '*');
- res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Token');
- res.setHeader('Access-Control-Expose-Headers', 'X-Token');
- // res.setHeader('Access-Control-Max-Age', config.maxAge);
- }
- checkBodyParams(req, routes, route) {
- for(let param in routes[route].body) {
- if(req.body.hasOwnProperty(param)) {
- if(routes[route].body[param].regex) {
- if(!req.body[param].match(routes[route].body[param].regex)) {
- return {
- status: false,
- error: routes[route].body[param].err ? routes[route].body[param].err : `wrong ${param} format!`
- };
- }
- }
- } else {
- return {status: false, error: `${param} param is required!`};
- }
- }
- return {status:true};
- }
- checkQueryParams(actualParams, validParams) {
- let diff = _.differenceWith(_.keys(actualParams), validParams, _.isEqual);
- return {status: diff.length == 0, error: 'Unacceptable params ' + diff};
- }
- checkFiles(actualFiles, validFiles) {
- let result = {status: true};
- for(let file in validFiles) {
- if(validFiles[file].required && !_.keys(actualFiles).includes(file)) {
- result.status = false;
- result.error = `No required file with name = "${file}" found!`;
- break;
- }
- if(validFiles[file].maxSize && _.keys(actualFiles).includes(file)) {
- let maxSize = File.size(validFiles[file].maxSize);
- if(actualFiles[file].size >= maxSize) {
- result.status = false;
- result.error = `The size of the file "${file}" is greater than ${validFiles[file].maxSize}!`;
- break;
- }
- }
- }
- return result;
- }
- __validateJWT(token) {
- if(token.match(/^Bearer.+/))
- token = token.replace(/^Bearer /i, '');
- try {
- return {validated:true, decoded: jwt.verify(token, __config.secretSalt)}
- } catch (e) {
- return {validated:false, err: e}
- }
- }
- __getQueryDict(route, reqPath) {
- let queryKeys = route.match(/(:\w+)/gi)||[];
- let splitedRoute = route.split('/');
- let splitedPath = reqPath.split('/');
- let indexes = queryKeys.map(__ => splitedRoute.indexOf(__))
- let queryDict = {};
- for(let i in queryKeys)
- queryDict[queryKeys[i].substr(1, queryKeys[i].length)] = splitedPath[indexes[i]];
- }
- async handleRequest(req, res) {
- LOGGER.route(req);
- for(let controllerName in controllers) {
- let routes = routesList[controllerName];
- for(let route in routes.routes) {
- // REPLACE IN-PATH VARIABLES(LIKE: /user/:id/update) WITH REGEX PATTERNS FOR FURTHER MATCHING
- let r = route.replace(new RegExp(':\\w+', 'g'), '(\\w+)');
- // IF PATH DID MATCH
- if((req.method + ':' + req.path).match(new RegExp('^'+r+'$', 'gi'))) {
- let decodedJWTData = null;
- let token = req.header('Authorization') || req.cookies.Authorization || req.query.Authorization;
- // IF ROUTE REQUIRES TOKEN SO CHECK ONE
- if(routes.requireToken) {
- let JWTToken = this.__validateJWT(token);
- if(!JWTToken.validated)
- return res.accessDenied();
- decodedJWTData = JWTToken.decoded;
- }
- // MERGE IN-PATH VARIABLES TO REQ.QUERY OBJECT
- _.merge(req.query, this.__getQueryDict(route, req.path));
- // CHECK QUERY RULES IF THEY EXIST IN ROUTE DECLARATION
- if(routes.routes[route].query) {
- let checkedQueryParams = this.checkQueryParams(req.query, routes.routes[route].query);
- if(!checkedQueryParams.status)
- return res.error(checkedQueryParams.error);
- }
- // CHECK BODY RULES IF THEY EXIST IN ROUTE DECLARATION
- if(routes.routes[route].body) {
- let checkedBodyParams = this.checkBodyParams(req, routes.routes, route);
- if(!checkedBodyParams.status)
- return res.error(checkedBodyParams.error);
- }
- // CHECK FILES RULES IF THEY EXIST IN ROUTE DECLARATION
- if(routes.routes[route].files) {
- let checkedFiles = this.checkFiles(req.files, routes.routes[route].files);
- if(!checkedFiles.status)
- return res.error(checkedFiles.error);
- }
- controllers[controllerName].user = decodedJWTData;
- controllers[controllerName].req = req;
- controllers[controllerName].res = res;
- return controllers[controllerName][routes.routes[route].action](req,res);
- }
- }
- }
- this.throw404(req, res)
- }
- throw404 (req, res) {
- return res.error('404');
- }
- }
- module.exports = Router;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement