diff --git a/package-lock.json b/package-lock.json index e3cc6f8..37cc429 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,7 +91,7 @@ "@types/bson": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/bson/-/bson-1.0.6.tgz", - "integrity": "sha512-v7N8qcTGiYhLRyi+Y69R3tPC4GLqByCg3NC2EO6PciC166O9dNhjFPoXeMePtZ+0f+/O2xLDWXs5BLnRfcBaBA==", + "integrity": "sha1-hpHwQtmd0WOl603W3eWH00SffNo=", "dev": true, "requires": { "@types/node": "9.4.6" @@ -193,7 +193,7 @@ "@types/form-data": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", - "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "integrity": "sha1-7is7jqoRwJOCiZU2BrdFtzjFSx4=", "dev": true, "requires": { "@types/node": "9.4.6" @@ -368,7 +368,7 @@ "@types/superagent": { "version": "3.5.6", "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-3.5.6.tgz", - "integrity": "sha1-nPJjLAdbqeYB9qYQqtwjmS0COUw=", + "integrity": "sha512-yGiVkRbB1qtIkRCpEJIxlHazBoILmu33xbbu4IiwxTJjwDi/EudiPYAD7QwWe035jkE40yQgTVXZsAePFtleww==", "dev": true, "requires": { "@types/node": "9.4.6" @@ -389,6 +389,15 @@ "integrity": "sha512-vOVmaruQG5EatOU/jM6yU2uCp3Lz6mK1P5Ztu4iJjfM4SVHU9XYktPUQtKlIXuahqXHdEyUarMrBEwg5Cwu+bA==", "dev": true }, + "@types/winston": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/winston/-/winston-2.3.8.tgz", + "integrity": "sha512-QqR0j08RCS1AQYPMRPHikEpcmK+2aEEbcSzWLwOqyJ4FhLmHUx/WjRrnn7tTQg/y4IKnMhzskh/o7qvGIZZ7iA==", + "dev": true, + "requires": { + "@types/node": "9.4.6" + } + }, "abab": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", @@ -398,7 +407,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, "accepts": { @@ -505,7 +514,7 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "are-we-there-yet": { @@ -1329,6 +1338,11 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -1406,7 +1420,7 @@ "configstore": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", - "integrity": "sha1-CU7mYquD+tmRdnjeEU+q6o/NypA=", + "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", "dev": true, "requires": { "dot-prop": "4.2.0", @@ -1586,6 +1600,11 @@ "array-find-index": "1.0.2" } }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1597,7 +1616,7 @@ "date-fns": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", - "integrity": "sha1-EuYJzcuTUScxHQTTMzTilgoqVOY=", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==", "dev": true }, "debug": { @@ -1712,7 +1731,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", "dev": true, "requires": { "is-obj": "1.0.1" @@ -2065,6 +2084,11 @@ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, "fast-deep-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", @@ -2232,7 +2256,7 @@ "fs-extra": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "integrity": "sha1-DYUhIuW8W+tFP7Ao6cDJvzY0DJQ=", "dev": true, "requires": { "graceful-fs": "4.1.11", @@ -5224,7 +5248,7 @@ "make-dir": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", - "integrity": "sha1-GbQ2n+SMEW9Twq+VrRAsDjnoXVE=", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", "dev": true, "requires": { "pify": "3.0.0" @@ -5882,7 +5906,7 @@ "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { "are-we-there-yet": "1.1.4", @@ -6760,11 +6784,21 @@ "uuid": "3.1.0" } }, + "request-promise": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz", + "integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=", + "requires": { + "bluebird": "3.5.1", + "request-promise-core": "1.1.1", + "stealthy-require": "1.1.1", + "tough-cookie": "2.3.3" + } + }, "request-promise-core": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", - "dev": true, "requires": { "lodash": "4.17.4" } @@ -7221,6 +7255,11 @@ "tweetnacl": "0.14.5" } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.1.tgz", @@ -7244,8 +7283,7 @@ "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" }, "stream-combiner": { "version": "0.0.4", @@ -7510,7 +7548,7 @@ "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", "dev": true, "requires": { "nopt": "1.0.10" @@ -7555,7 +7593,7 @@ "tree-kill": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", - "integrity": "sha1-WEZ4Yje0I5AU8F2xVrZDIS1MbzY=", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==", "dev": true }, "trim-newlines": { @@ -7955,7 +7993,7 @@ "ansi-styles": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { "color-convert": "1.9.0" @@ -7964,7 +8002,7 @@ "chalk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { "ansi-styles": "3.2.0", @@ -8036,7 +8074,7 @@ "validator": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/validator/-/validator-8.2.0.tgz", - "integrity": "sha1-PBI3KQ43CSNVNE/veMIxJJ2rd7k=" + "integrity": "sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA==" }, "vary": { "version": "1.1.2", @@ -8138,7 +8176,7 @@ "wide-align": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "requires": { "string-width": "1.0.2" @@ -8186,6 +8224,26 @@ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" }, + "winston": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.0.tgz", + "integrity": "sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=", + "requires": { + "async": "1.0.0", + "colors": "1.0.3", + "cycle": "1.0.3", + "eyes": "0.1.8", + "isstream": "0.1.2", + "stack-trace": "0.0.10" + }, + "dependencies": { + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + } + } + }, "with": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", diff --git a/package.json b/package.json index c898385..51f03f8 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,9 @@ "passport-facebook": "^2.1.1", "passport-local": "^1.0.0", "pug": "^2.0.0-rc.4", - "request": "^2.83.0" + "request": "^2.83.0", + "request-promise": "^4.2.2", + "winston": "^2.4.0" }, "devDependencies": { "@types/async": "^2.0.45", @@ -76,6 +78,7 @@ "@types/request": "^2.47.0", "@types/shelljs": "^0.7.8", "@types/supertest": "^2.0.4", + "@types/winston": "^2.3.7", "chai": "^4.1.2", "concurrently": "^3.5.1", "jest": "^22.0.4", diff --git a/src/app.ts b/src/app.ts index f300733..b99e44e 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,7 +2,7 @@ import express from "express"; import compression from "compression"; // compresses requests import session from "express-session"; import bodyParser from "body-parser"; -import logger from "morgan"; +import logger from "./util/logger"; import lusca from "lusca"; import dotenv from "dotenv"; import mongo from "connect-mongo"; @@ -12,7 +12,7 @@ import mongoose from "mongoose"; import passport from "passport"; import expressValidator from "express-validator"; import bluebird from "bluebird"; -import { MONGODB_URI, SESSION_SECRET } from "./util/loadSecrets"; +import { MONGODB_URI, SESSION_SECRET } from "./util/secrets"; const MongoStore = mongo(session); @@ -33,7 +33,7 @@ import * as passportConfig from "./config/passport"; const app = express(); // Connect to MongoDB -const mongoUrl = process.env.MONGOLAB_URI; +const mongoUrl = MONGODB_URI; (mongoose).Promise = bluebird; mongoose.connect(mongoUrl, {useMongoClient: true}).then( () => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ }, @@ -47,14 +47,13 @@ app.set("port", process.env.PORT || 3000); app.set("views", path.join(__dirname, "../views")); app.set("view engine", "pug"); app.use(compression()); -app.use(logger("dev")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(expressValidator()); app.use(session({ resave: true, saveUninitialized: true, - secret: process.env.SESSION_SECRET, + secret: SESSION_SECRET, store: new MongoStore({ url: mongoUrl, autoReconnect: true diff --git a/src/util/logger.ts b/src/util/logger.ts new file mode 100644 index 0000000..4004e6e --- /dev/null +++ b/src/util/logger.ts @@ -0,0 +1,16 @@ +import * as winston from "winston"; +import { ENVIRONMENT } from "./secrets"; + +const logger = new (winston.Logger)({ + transports: [ + new (winston.transports.Console)({ level: process.env.NODE_ENV === "production" ? "error" : "debug" }), + new (winston.transports.File)({ filename: "debug.log", level: "debug"}) + ] +}); + +if (process.env.NODE_ENV !== "production") { + logger.debug("Logging initialized at debug level"); +} + +export default logger; + diff --git a/src/util/secrets.ts b/src/util/secrets.ts new file mode 100644 index 0000000..bc6d27a --- /dev/null +++ b/src/util/secrets.ts @@ -0,0 +1,26 @@ +import logger from "./logger"; +import * as dotenv from "dotenv"; +import * as fs from "fs"; + +if (fs.existsSync(".env")) { + logger.debug("Using .env file to supply config environment variables"); + dotenv.config({ path: ".env" }); +} else { + logger.debug("Using .env.example file to supply config environment variables"); + dotenv.config({ path: ".env.example" }); // you can delete this after you create your own .env file! +} +export const ENVIRONMENT = process.env.NODE_ENV; +const prod = ENVIRONMENT === "production"; // Anything else is treated as 'dev' + +export const SESSION_SECRET = process.env["SESSION_SECRET"]; +export const MONGODB_URI = prod ? process.env["MONGODB_URI"] : process.env["MONGODB_URI_LOCAL"]; + +if (!SESSION_SECRET) { + logger.error("No client secret. Set SESSION_SECRET environment variable."); + process.exit(1); +} + +if (!MONGODB_URI) { + logger.error("No mongo connection string. Set MONGODB_URI environment variable."); + process.exit(1); +}