hexlet-volunteers/interviews

View on GitHub
app.js

Summary

Maintainability
A
1 hr
Test Coverage
// @flow

import express from 'express';
import morgan from 'morgan';
import mincer from 'mincer';
import path from 'path';
import Router from 'named-routes';
import debug from 'debug';
import cookieParser from 'cookie-parser';
import bodyParser from 'body-parser';
import sequelize from './db';
import passport from 'passport';
import configurePassport from './auth/github';
import saveFormData from './helpers/hooks';

import home from './routes/index';
import about from './routes/about';

const debugServer = debug('interview:server');
const debugError = debug('interview:error');
const app = express();

const passportGithubEnv = {
  github_client_id: process.env.GITHUB_CLIENT_ID || 'hexlet',
  github_client_secret: process.env.GITHUB_CLIENT_SECRET || 'LISP',
  github_callback: process.env.GITHUB_CALLBACK || 'http://127.0.0.1/login/callback',
};

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// logging setup
app.use(morgan('dev'));
mincer.logger.use(debug('interview:mincer'));
mincer.MacroProcessor.configure('.css');

// assets pipeline setup
let environment = new mincer.Environment();
environment.enable('source_maps');
environment.enable('autoprefixer');
environment.appendPath('public/stylesheets');
environment.appendPath('public/javascripts');
environment.appendPath('public/images');
environment.appendPath('node_modules');

environment.ContextClass.defineAssetPath((pathname, options) => {
  const asset = environment.findAsset(pathname, options);
  if (!asset) {
    throw new Error(`File ${pathname} not found`);
  }
  return `/assets/${asset.digestPath}`;
});

app.use('/assets', mincer.createServer(environment));

app.use(require('express-session')({
  secret: 'LISPy cat',
  resave: true,
  saveUninitialized: true,
}));

configurePassport(passportGithubEnv);
app.use(passport.initialize());
app.use(passport.session());

if (process.env.NODE_ENV === 'production') {
  environment.cache = new mincer.FileStore(path.join(__dirname, 'cache'));
  environment.jsCompressor = 'uglify';
  environment.cssCompressor = 'csswring';
  environment = environment.index;
}

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());

// db setup
const force = process.env.NODE_ENV !== 'production';
sequelize.sync({ force }).then(() => {
  debugServer('connected to database');
});

// routing setup
const router = new Router();
router.extendExpress(app);
router.registerAppHelpers(app);

home.registerRoutes(app);
about.registerRoutes(app);

async function saveToDb(data, reqType) {
  if (reqType === 'add-applicant') {
    debugServer('POST /add-applicant', data);
    const res = await sequelize.models.user.createApplicant(data);
    debugServer('Result', res);
  } else if (reqType === 'add-interviewer') {
    debugServer('POST /add-interviewer', data);
    const res = await sequelize.models.user.createInterviewer(data);
    debugServer('Result', res);
  }
}

app.get('/login/callback', 'callback', passport.authenticate('github', { failureRedirect: '/' }),
  (req, res) => {
    const data = req.session.initBody;
    const type = req.session.requestType;
    data.email = req.user.emails[0].value;

    return process.nextTick(() => {
      if (data) {
        saveToDb(data, type);
      } else {
        return res.send('Something bad just happened');
      }
      return res.redirect(app.namedRoutes.build('home'));
    });
  }
);

app.post('/add-interviewer', 'add-interviewer', saveFormData, passport.authenticate('github'));
app.post('/add-applicant', 'add-applicant', saveFormData, passport.authenticate('github'));


// catch 404 and forward to error handler
app.use((req, res, next) => {
  const errorInfo = {
    error: new Error('Not found'),
    status: 404,
  };
  next(errorInfo);
});

// development error handler
// will print stacktrace
app.use(({ error, status }, req, res) => {
  debugError(error);
  res.status(status || 500);
  res.render('error', {
    message: error.message,
    status,
    error,
  });
});


// production error handler
// no stacktraces leaked to user
if (app.get('env') === 'production') {
  app.use(({ error, status }, req, res) => {
    debugError(error);
    res.status(status || 500);
    res.render('error', {
      message: error.message,
      status,
      error: {},
    });
  });
}
module.exports = app;