125 lines
3.6 KiB
JavaScript
125 lines
3.6 KiB
JavaScript
/*
|
|
* This file defines the routes for the web portal running on the api server
|
|
* It uses express router so it can be placed under any path, and will then
|
|
* assume everything else is under the root of that path.
|
|
* e.g. to place under /portal/ you would do:
|
|
*
|
|
* var appHttps = [main app setup]
|
|
* var portalRouterFactory = require(<this file>);
|
|
* var portalRouter = portalRouterFactory(<filesystem path to portal files>);
|
|
* appHttps.use('/portal/', portalRouter);
|
|
*/
|
|
const path = require('path');
|
|
const express = require('express');
|
|
const bodyParser = require('body-parser');
|
|
const compression = require('compression');
|
|
const RateLimit = require('express-rate-limit');
|
|
const helmet = require('helmet');
|
|
|
|
const config = require(global.configFile);
|
|
|
|
/**
|
|
* Content security policy options
|
|
*/
|
|
const cspOptions = {
|
|
directives: {
|
|
defaultSrc: ['\'self\''],
|
|
|
|
/**
|
|
* Image Sources:
|
|
* - self: image served from the exact domain and scheme
|
|
* - *.base.maps.api.here.com: map tile server for normal tiles
|
|
* - *.aerial.maps.api.here.com: map tile server for satellite tiles
|
|
* - data: images from data uris (used for profile pics etc.)
|
|
*/
|
|
imgSrc: [
|
|
'\'self\'',
|
|
'https://*.base.maps.api.here.com',
|
|
'https://*.aerial.maps.api.here.com',
|
|
'data:'
|
|
],
|
|
|
|
/**
|
|
* Frame Source:
|
|
* - www.comcarde.com for the framed updated terms and conditions
|
|
*/
|
|
frameSrc: ['https://www.comcarde.com'],
|
|
|
|
/**
|
|
* Connect Source
|
|
* - 'self': API requests, etc.
|
|
* - *.base.maps.api.here.com: copyright attribution info for normal tiles
|
|
* - *.aerial.maps.api.here.com: copyright attribution info for satellite tiles
|
|
*/
|
|
connectSrc: [
|
|
'\'self\'',
|
|
'https://*.base.maps.api.here.com',
|
|
'https://*.aerial.maps.api.here.com'
|
|
],
|
|
|
|
reportUri: '/api/v0/csp-report'
|
|
},
|
|
reportOnly: false
|
|
};
|
|
|
|
module.exports = (function() {
|
|
return function portalRouterFactory(filePath) {
|
|
const router = express.Router();
|
|
|
|
/* Body Parsers, including for application/csp-report */
|
|
router.use(bodyParser.json({type: 'application/json'}));
|
|
router.use(bodyParser.json({type: 'application/csp-report'}));
|
|
|
|
/*
|
|
* Rate Limiting
|
|
*/
|
|
const limiter = new RateLimit(config.rateLimits.portalStatic);
|
|
router.use(limiter);
|
|
|
|
/*
|
|
* Content Security Policy (CSP) headers
|
|
*/
|
|
router.use(helmet.contentSecurityPolicy(cspOptions));
|
|
|
|
/*
|
|
* Enable compression
|
|
*/
|
|
router.use(compression());
|
|
|
|
/*
|
|
* Serve basic available files
|
|
*/
|
|
router.use(express.static(filePath));
|
|
|
|
/*
|
|
* JSON translation files
|
|
*/
|
|
router.use(
|
|
express.static(path.resolve(filePath, './app/*/i18n/*.json'))
|
|
);
|
|
|
|
/*
|
|
* If the request looks like a request for a template, and the template
|
|
* doesn't exists, return a 404.
|
|
*/
|
|
router.use('/app/*', (req, res) => {
|
|
res.status(404).end();
|
|
});
|
|
|
|
/*
|
|
* Any other requests are guessed to be from the manipulated URLs for the
|
|
* pages in the web app. So we serve index.html in response to them, which
|
|
* will kickstart everything
|
|
*/
|
|
router.use(
|
|
'/*',
|
|
express.static(path.resolve(filePath, './index.html'))
|
|
);
|
|
|
|
/*
|
|
* Return the configured router
|
|
*/
|
|
return router;
|
|
};
|
|
})();
|