uplink/src/app.ts

148 lines
4.1 KiB
TypeScript

import logger from './logger';
import path from 'path';
/*
* Express-relateed imports that we need because this is running primarily over
* REST
*/
import cookieParser from 'cookie-parser';
import favicon from 'serve-favicon';
import compress from 'compression';
import helmet from 'helmet';
import cors from 'cors';
import * as Sentry from '@sentry/node';
/**/
/*
* Feathers specific imports for setting up the application
*/
import feathers from '@feathersjs/feathers';
import configuration from '@feathersjs/configuration';
import authentication from '@feathersjs/authentication';
import jwt from '@feathersjs/authentication-jwt';
import oauth2 from '@feathersjs/authentication-oauth2';
import { Strategy } from 'passport-github';
import express from '@feathersjs/express';
import socketio from '@feathersjs/socketio';
/**/
import middleware from './middleware';
import services from './services';
import { appHooks } from './app.hooks';
import channels from './channels';
import Admin from './controllers/admin';
import Dashboard from './controllers/dashboard';
import Export from './controllers/export';
const app = express(feathers());
const settings = configuration();
if (process.env.SENTRY_DSN) {
Sentry.init({ dsn: process.env.SENTRY_DSN })
/*
* Cannot case to RequestHandler per Sentry's docs due to compilation error:
*
* src/app.ts:48:11 - error TS2352: Type '(req: ClientRequest, res:
* ServerResponse, next: () => void) => void' cannot be converted to type
* 'RequestHandler'.
* Types of parameters 'req' and 'req' are incompatible.
* Type 'Request' is not comparable to type 'ClientRequest'.
* Property 'aborted' is missing in type 'Request'.
*
* 48 app.use(Sentry.Handlers.requestHandler() as
* RequestHandler);
*/
app.use(Sentry.Handlers.requestHandler() as any);
logger.info('Sentry configured and installed');
}
// Load app configuration
app.configure(settings);
// Enable security, CORS, compression, favicon and body parsing
app.use(helmet());
app.use(cors());
app.use(compress());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(favicon(path.join(app.get('public'), 'favicon.ico')));
// Host the public folder
app.use('/', express.static(app.get('public')));
// Set up Plugins and providers
app.configure(express.rest());
app.configure(socketio());
/*
* Enabling the cookie parser on all requests to make sure we can use the JWT
* authentication wherever we damn well please
*/
app.get('*', cookieParser());
app.post('*', cookieParser());
/*
* Ensure that POST calls which have _method set to DELETE get passed through
* properly
*/
app.post('*', (req, res, next) => {
if (req.body._method == 'DELETE') {
req.method = req.body._method;
}
next();
});
/*
* Allow overriding the JWT secret in the environment, a la Kubernetes
*/
app.get('authentication').secret = process.env.JWT_SECRET || app.get('authentication').secret;
app.configure(authentication(app.get('authentication')));
app.configure(jwt());
const githubSettings = app.get('github');
if (process.env.NODE_ENV == 'production') {
githubSettings.clientID = process.env.CLIENT_ID || githubSettings.clientID;
githubSettings.clientSecret = process.env.CLIENT_SECRET || githubSettings.clientSecret;
}
app.configure(oauth2(Object.assign(githubSettings, {
name: 'github',
Strategy: Strategy,
successRedirect: '/dashboard',
scope: [],
})));
app.set('view engine', 'pug');
Dashboard(app);
Export(app);
Admin(app);
app.get('/logout',
cookieParser(),
(req, res, next) => {
res.clearCookie(app.get('authentication').cookie.name);
res.redirect('/');
});
// Configure other middleware (see `middleware/index.js`)
app.configure(middleware);
// Set up our services (see `services/index.js`)
app.configure(services);
// Set up event channels (see channels.js)
app.configure(channels);
// The error handler must be before any other error middleware
app.use(Sentry.Handlers.errorHandler() as any);
// Configure a middleware for 404s and the error handler
app.use(express.notFound());
app.use(express.errorHandler({ logger }));
app.hooks(appHooks);
export default app;