initial commit

This commit is contained in:
JJ Kasper
2018-05-17 14:31:05 -05:00
commit 2c90d2e7dd
79 changed files with 10684 additions and 0 deletions

117
src/app.js Normal file
View File

@@ -0,0 +1,117 @@
const favicon = require('serve-favicon');
const fs = require('fs');
const path = require('path');
const compress = require('compression');
const cors = require('cors');
const helmet = require('helmet');
const cookieParser = require('cookie-parser')();
const RateLimit = require('express-rate-limit');
const trustIPs = require('./trustIPs');
const logger = require('winston');
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const configuration = require('@feathersjs/configuration');
const hostConfig = require('../config/host.json');
const middleware = require('./middleware');
const services = require('./services');
const appHooks = require('./app.hooks');
const channels = require('./channels');
const authentication = require('./authentication');
const dev = process.env.NODE_ENV !== 'production';
const basePath = require('../util/basePath');
const stripBase = require('../util/stripBase');
const getUrl = require('../util/getUrl');
const { parse } = require('url');
const nxt = require('next')({ dev, quiet: true });
const nxtHandler = nxt.getRequestHandler();
const app = express(feathers());
app.startNext = () => nxt.prepare();
app.configure(configuration()); // Load app configuration
Object.keys(hostConfig).forEach(key => ( // load host config
app.set(key, hostConfig[key])
));
app.set('didSetup', false);
try {
fs.statSync(path.join(__dirname, '..', 'db', '.didSetup'));
app.set('didSetup', true);
}
catch(err) {
app.use((req, res, next) => {
req.doSetup = !app.get('didSetup');
next();
});
}
const authLimit = new RateLimit({
windowMs: 5 * 60 * 1000, // 5 minutes
max: 5, // 5 attempts then block
delayAfter: 3, // slow down after 3 fails
delayMs: 2 * 1000
});
app.authLimit = authLimit;
app.use(getUrl('auth'), authLimit);
app.patch(getUrl('users/*'), authLimit);
// Enable CORS, security, compression, favicon and body parsing
trustIPs(app);
app.use(cors());
app.use(helmet({
hidePoweredBy: { setTo: 'hamsters' }
}));
if(!dev) app.use(compress());
app.use(express.json()); // use { limit } option to increase max post size
app.use(express.urlencoded({ extended: true }));
app.use(getUrl('/'), favicon('favicon.ico'));
app.configure(express.rest()); // Set up Plugins and providers
app.configure(middleware); // middleware/index.js
app.configure(authentication); // Set up authentication
app.configure(services); // Set up our services (see `services/index.js`)
app.configure(channels); // Set up event channels (see channels.js)
const checkJWT = async (req, res, next) => {
const result = await req.app.authenticate('jwt', {})(req);
if(result.success) {
req.jwt = req.cookies.jwt;
delete result.data.user.password;
req.user = result.data.user;
}
next();
};
nxt.setAssetPrefix(basePath); // setup next.js routes
[ '/', '/logout', '/new', '/settings' ]
.forEach(route => {
app.get(getUrl(route), cookieParser, checkJWT, (req, res) => {
const { query } = parse(req.url, true);
nxt.render(req, res, route, query);
});
});
[ '/k', '/edit' ]
.forEach(route => {
app.get(getUrl(route + '/:id'), cookieParser, checkJWT, (req, res) => {
nxt.render(req, res, route, { id: req.params.id });
});
});
const notFound = express.notFound();
app.use((req, res, next) => {
let accept = req.get('accept');
if(accept && accept.toLowerCase() === 'application/json')
return notFound(req, res, next);
if(req.url.substr(0, basePath.length) !== basePath)
return nxt.render404(req, res);
nxtHandler(req, res, parse(stripBase(req.url), true));
});
app.use(express.errorHandler({ logger }));
app.hooks(appHooks);
module.exports = app;