{"size": 4081, "ext": "js", "max_stars_repo_path": "index.js", "max_stars_repo_name": "ryanweal/hits", "max_stars_repo_stars_event_min_datetime": "2020-12-14T13:22:24.000Z", "max_stars_repo_stars_event_max_datetime": "2020-12-14T13:22:24.000Z", "max_issues_repo_path": "index.js", "max_issues_repo_name": "ryanweal/hits", "max_issues_repo_issues_event_min_datetime": "2020-09-04T16:40:05.000Z", "max_issues_repo_issues_event_max_datetime": "2021-09-01T20:33:22.000Z", "max_forks_repo_path": "index.js", "max_forks_repo_name": "ryanweal/hits", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 1, "max_issues_count": 3, "max_forks_count": null, "avg_line_length": 26.6732026144, "max_line_length": 143, "alphanum_fraction": 0.6089193825}
'use strict';

const {
  initCassandraAsync
} = require('./src/cassandra.js');
const express = require('express');
const bodyParser = require('body-parser');
const Promise = require('bluebird');
const helmet = require('helmet');
const nodeLimits = require('limits');

const reqDuration = 2629746000; // 1-month hsts

const auth = require('./controllers/auth.js');
const hits = require('./controllers/hits.js');
const counter = require('./controllers/counter.js');

console.log('Node', process.version);
console.log('info Remember to only run even-numbered (LTS) versions of node in production.');

// Allow bluebird promise cancellation
Promise.config({
  cancellation: true
});

/**
 * Connect to Cassandra and start Express
 */
function startAsync() {
  // Start by initializing cassandra
  return initCassandraAsync()
    // Create any tables here
    .then(client => {
      return auth.createTable(client);
    })
    .then(client => {
      return hits.createTable(client);
    })
    .then(client => {
      return counter.createTable(client);
    })
    // Start the express server to process requests
    .then(() => {
      const app = express();
      app.use(bodyParser.json({
        limit: '1mb' // limit string length
      }));
      app.use(bodyParser.urlencoded({
        extended: true
      }));

      // security by obscurity (helmet does this also)
      app.disable('x-powered-by');

      // helmet
      app.use(helmet());

      // hsts
      app.use(helmet.hsts({
        maxAge: reqDuration
      }));

      // framebuster
      app.use(helmet.frameguard({
        action: 'deny'
      }));

      // content security policy
      app.use(helmet.contentSecurityPolicy({
        directives: {
          defaultSrc: ["'self'"],
          scriptSrc: ["'self'"],
          childSrc: ["'none'"],
          objectSrc: ["'none'"],
          formAction: ["'none'"],
        }
      }));

      // x-xss-protection (disabled for ie8/ie9 which opens vulnerability)
      app.use(helmet.xssFilter());

      // x-content-type-options
      app.use(helmet.noSniff());

      // limit some things
      app.use(nodeLimits({
        file_uploads: false,
        post_max_size: 1000000,   // 1mb max upload
        inc_req_timeout: 1000*60  // 60 seconds 
      }))

      app.use(function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header('Access-Control-Allow-Methods', 'POST');
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        next();
      });

      const port = 4000;

      app.get('/', (req, res) => res.send('Hello World!'));

      app.post('/register', (req, res) => auth.register(req,res));
      app.post('/login', (req, res) => auth.login(req,res));
      app.post('/testcleanup', (req, res) => auth.testcleanup(req,res));

      app.post('/hit', (req, res) => hits.hit(req,res));

      app.listen(port, () => console.log(`info Express listening on port ${port}!`))

      return app;
    })
    .catch(err => {
      // Use console to log error since logger might write asynchronously
      console.error(err);
      process.exit(1);
    });
}

let startPromise = startAsync();


/**
 * Handle stopping everything. From Datastax example.
 */
function stop() {
  console.log('info', 'Attempting to shutdown');
  if (startPromise.isFulfilled()) {
    let server = startPromise.value();
    return new Promise((resolve, reject) => {
      resolve(server.removeAllListeners());
    })
    .then(() => process.exit(0));
  } else {
    startPromise.cancel();
    process.exit(0);
  }
}

// Try to gracefully shutdown on SIGTERM and SIGINT
process.on('SIGTERM', stop);
process.on('SIGINT', stop);

// Graceful shutdown attempt in Windows
if (process.platform === 'win32') {
  // Simulate SIGINT on Windows (see http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js)
  createInterface({
      input: process.stdin,
      output: process.stdout
    })
    .on('SIGINT', () => process.emit('SIGINT'));
}
