thegameofcode/cipherlayer

View on GitHub
src/public_service.js

Summary

Maintainability
D
2 days
Test Coverage
'use strict';

const passport = require('passport');
const _ = require('lodash');
const restify = require('restify');
const fs = require('fs');
const path = require('path');
const versionControl = require('version-control');

const config = require('../config');
const log = require('./logger/service');
const checkAccessTokenParam = require('./middlewares/accessTokenParam');
const checkAuthHeader = require('./middlewares/authHeaderRequired');
const decodeToken = require('./middlewares/decodeToken');
const findUser = require('./middlewares/findUser');
const prepareOptions = require('./middlewares/prepareOptions');
const platformsSetUp = require('./middlewares/platformsSetUp');
const propagateRequest = require('./middlewares/propagateRequest');
const permissions = require('./middlewares/permissions');
const bodyParserWrapper = require('./middlewares/bodyParserWrapper');
const pinValidation = require('./middlewares/pinValidation')();
const userAppVersion = require('./middlewares/userAppVersion')();

const routes = require('./routes_public/routes');

const service = {};
let server;

module.exports = function () {

    service.start = function (publicPort, done) {
        server = restify.createServer({
            name: 'cipherlayer-server',
            log
        });

        log.info(`PUBLIC SERVICE starting on PORT ${publicPort}`);

        server.on('after', function (req, res) {
            const logInfo = {
                request: {
                    method: req.method,
                    headers: req.headers,
                    url: req.url,
                    path: req._url.pathname,
                    query: req._url.query,
                    params: req.params,
                    time: req._time
                },
                response: {
                    statusCode: res.statusCode,
                    hasBody: res.hasBody,
                    bodySize: _.size(res.body),
                    time: Date.now()
                },
                user: req.user,
                tokenInfo: req.tokenInfo
            };

            if (logInfo.request.params && logInfo.request.params.password) {
                delete(logInfo.request.params.password);
            }

            req.log.info(logInfo, 'response');
        });

        if (config.accessControlAllow) {
            server.use(restify.CORS({
                origins: config.accessControlAllow.origins,
                credentials: true,
                headers: config.accessControlAllow.headers
            }));

            server.opts(/.*/, function (req, res, next) {
                res.header('Access-Control-Allow-Methods', req.header('Access-Control-Request-Methods'));
                res.header('Access-Control-Allow-Headers', req.header('Access-Control-Request-Headers'));
                if(req.header('Access-Control-Allow-Origin') === config.accessControlAllow.origins){
                    res.header('Access-Control-Allow-Origin', config.accessControlAllow.origins);
                }
                res.send(200);
                return next();
            });
        }

        server.use(restify.queryParser());
        server.use(bodyParserWrapper(restify.bodyParser({maxBodySize: 1024 * 1024 * 3})));

        const versionControlOptions = _.clone(config.version);
        versionControlOptions.public = [
            '/auth/sf',
            '/auth/sf/*',
            '/auth/login/refreshToken*',
            '/user/activate*',
            '/heartbeat',
            '/user/email/available'
        ];
        if (config.version.public) {
            versionControlOptions.public = versionControlOptions.public.concat(config.version.public);
        }
        server.use(versionControl(versionControlOptions));

        server.on('uncaughtException', function (req, res, route, error) {
            log.error({exception: {req, res, route, err: error}}, 'uncaught exception');
            if (!res.statusCode) {
                res.send(500, {err: 'internal_error', des: 'uncaught exception'});
            }
        });

        routes(server);

        const platformsPath = path.join(__dirname, '/platforms/');
        fs.readdirSync(platformsPath).forEach(function (filename) {
            require(platformsPath + filename).addRoutes(server, passport);
        });

        const allMiddlewares = [
            checkAccessTokenParam,
            checkAuthHeader,
            decodeToken,
            permissions,
            findUser,
            pinValidation,
            userAppVersion,
            prepareOptions,
            platformsSetUp,
            propagateRequest
        ];

        if (config.publicEndpoints) {
            config.publicEndpoints.forEach(publicEndpoint => {
                publicEndpoint.replace('*','.*');
                const regEx = new RegExp(publicEndpoint);
                server.get(regEx, prepareOptions,propagateRequest);
                server.post(regEx, prepareOptions,propagateRequest);
            });
        }

        server.get(/(.*)/, allMiddlewares);
        server.post(/(.*)/, allMiddlewares);
        server.del(/(.*)/, allMiddlewares);
        server.put(/(.*)/, allMiddlewares);

        server.listen(publicPort, function () {
            log.info(`PUBLIC SERVICE listening on PORT ${publicPort}`);
            return done();
        });
    };

    service.stop = function (done) {
        server.close(function () {
            return done();
        });
    };

    return service;
}();