From 1dc6841728c6d2de6c712491405a994c660bf5ce Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 10:33:48 -0500 Subject: [PATCH 01/14] update stability ignores --- .cfignore | 4 +++- .gitignore | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.cfignore b/.cfignore index b512c09d..2099835f 100644 --- a/.cfignore +++ b/.cfignore @@ -1 +1,3 @@ -node_modules \ No newline at end of file +node_modules +run.sh +VCAP_SERVICES.json diff --git a/.gitignore b/.gitignore index 28f1ba75..08f7c23e 100755 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules -.DS_Store \ No newline at end of file +.DS_Store +run.sh +VCAP_SERVICES.json From 5f21f4c270592315f73ee707cfc2307c18fdf6d1 Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 10:35:48 -0500 Subject: [PATCH 02/14] add google analytics to as env var --- app.js | 3 +++ views/index.ejs | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/app.js b/app.js index 942913f7..0dde7da4 100755 --- a/app.js +++ b/app.js @@ -34,6 +34,9 @@ var toneAnalyzer = watson.tone_analyzer({ app.get('/', function(req, res) { res.render('index'); + res.render('index', { + ga: process.env.GOOGLE_ANALYTICS + }); }); app.post('/api/tone', function(req, res, next) { diff --git a/views/index.ejs b/views/index.ejs index 43d95e62..edf0e727 100755 --- a/views/index.ejs +++ b/views/index.ejs @@ -337,6 +337,15 @@ + From 4834bc60031c03fcd6f463fd57166aecddf8d295 Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 11:01:26 -0500 Subject: [PATCH 03/14] add csrf --- app.js | 2 +- config/express.js | 6 +++--- config/security.js | 13 +++++++++++++ package.json | 2 ++ views/index.ejs | 1 + 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 0dde7da4..57bc4a8e 100755 --- a/app.js +++ b/app.js @@ -33,8 +33,8 @@ var toneAnalyzer = watson.tone_analyzer({ }); app.get('/', function(req, res) { - res.render('index'); res.render('index', { + ct: req._csrfToken, ga: process.env.GOOGLE_ANALYTICS }); }); diff --git a/config/express.js b/config/express.js index 9baa3478..da1545ff 100755 --- a/config/express.js +++ b/config/express.js @@ -32,8 +32,8 @@ module.exports = function (app) { // Setup static public directory app.use(express.static(__dirname + '/../public')); - // Only loaded when SECURE_EXPRESS is `true` - if (process.env.SECURE_EXPRESS) + // Only loaded when VCAP_APPLICATION is `true` + if (process.env.VCAP_APPLICATION) require('./security')(app); -}; \ No newline at end of file +}; diff --git a/config/security.js b/config/security.js index 680e55a6..126ad5cd 100644 --- a/config/security.js +++ b/config/security.js @@ -20,6 +20,8 @@ var secure = require('express-secure-only'), rateLimit = require('express-rate-limit'), helmet = require('helmet'); + csrf = require('csurf'), + cookieParser = require('cookie-parser'); module.exports = function (app) { app.enable('trust proxy'); @@ -42,4 +44,15 @@ module.exports = function (app) { }); app.use('/api/', limiter); + // 3. setup cookies + var secret = Math.random().toString(36).substring(7); + app.use(cookieParser(secret)); + + // 4. csrf + var csrfProtection = csrf({ cookie: true }); + app.get('/', csrfProtection, function(req, res, next) { + console.log(req.csrfToken()); + req._csrfToken = req.csrfToken(); + next(); + }); }; diff --git a/package.json b/package.json index 3286db4d..a5e3ed0b 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ }, "dependencies": { "body-parser": "^1.13.2", + "cookie-parser": "^1.4.1", + "csurf": "^1.8.3", "ejs": "^2.3.4", "errorhandler": "^1.4.1", "express": "^4.12.2", diff --git a/views/index.ejs b/views/index.ejs index edf0e727..2b942ef0 100755 --- a/views/index.ejs +++ b/views/index.ejs @@ -7,6 +7,7 @@ + From 25d162f90da4f360c87ecf48e189b666df590dfa Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 11:03:29 -0500 Subject: [PATCH 04/14] add csrf protection in js --- public/js/demo.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/public/js/demo.js b/public/js/demo.js index 6202175a..4be0cc60 100755 --- a/public/js/demo.js +++ b/public/js/demo.js @@ -21,6 +21,14 @@ * JQuery on ready callback function */ function ready() { + + // CSRF protection + $.ajaxSetup({ + headers: { + 'csrf-token': $('meta[name="ct"]').attr('content') + } + }); + // load all json data first $.when( $.ajax('/data/threshold_v0.1.1.json'), From cc4b9a0ae3dadb587a89047e513f3f5d2e8d071a Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 11:04:02 -0500 Subject: [PATCH 05/14] clean security.js --- config/security.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/config/security.js b/config/security.js index 126ad5cd..860327a4 100644 --- a/config/security.js +++ b/config/security.js @@ -17,23 +17,19 @@ 'use strict'; // security.js -var secure = require('express-secure-only'), - rateLimit = require('express-rate-limit'), - helmet = require('helmet'); +var rateLimit = require('express-rate-limit'), + helmet = require('helmet'), csrf = require('csurf'), cookieParser = require('cookie-parser'); module.exports = function (app) { app.enable('trust proxy'); - // 1. redirects http to https - app.use(secure()); + // 1. helmet with defaults + app.use(helmet({ cacheControl: false })); - // 2. helmet with defaults - app.use(helmet()); - - // 3. rate limiting - var limiter = rateLimit({ + // 2. rate limiting + app.use('/api/', rateLimit({ windowMs: 30 * 1000, // seconds delayMs: 0, max: 6, @@ -41,9 +37,8 @@ module.exports = function (app) { error:'Too many requests, please try again in 30 seconds.', code: 429 }), - }); + })); - app.use('/api/', limiter); // 3. setup cookies var secret = Math.random().toString(36).substring(7); app.use(cookieParser(secret)); From 7f44ca00d23d2c6582ce102c9fb2e2888cd5f4ff Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 11:07:19 -0500 Subject: [PATCH 06/14] integrate cf-deployment-tracker-client --- app.js | 4 +--- package.json | 3 ++- server.js | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 server.js diff --git a/app.js b/app.js index 57bc4a8e..7dc24986 100755 --- a/app.js +++ b/app.js @@ -51,6 +51,4 @@ app.post('/api/tone', function(req, res, next) { // error-handler application settings require('./config/error-handler')(app); -var port = process.env.VCAP_APP_PORT || 3000; -app.listen(port); -console.log('listening at:', port); +module.exports = app; diff --git a/package.json b/package.json index a5e3ed0b..4067f9a4 100644 --- a/package.json +++ b/package.json @@ -26,10 +26,11 @@ "url": "https://github.com/watson-developer-cloud/tone-analyzer-nodejs/issues" }, "scripts": { - "start": "node app.js" + "start": "node server.js", }, "dependencies": { "body-parser": "^1.13.2", + "cf-deployment-tracker-client": "0.0.8", "cookie-parser": "^1.4.1", "csurf": "^1.8.3", "ejs": "^2.3.4", diff --git a/server.js b/server.js new file mode 100644 index 00000000..251977bd --- /dev/null +++ b/server.js @@ -0,0 +1,15 @@ +#! /usr/bin/env node +'use strict'; + +if (process.env.GOOGLE_ANALYTICS){ + process.env.GOOGLE_ANALYTICS = process.env.GOOGLE_ANALYTICS.replace(/\"/g,''); +} +// Deployment tracking +require('cf-deployment-tracker-client').track(); + +var server = require('./app'); +var port = process.env.PORT || process.env.VCAP_APP_PORT || 3000; + +server.listen(port, function () { + console.log('Server running on port: %d', port); +}); From 26149795885eb99e7ab50ffcf8509c793bfc367a Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 11:09:11 -0500 Subject: [PATCH 07/14] add privacy notice for cf-deployment-tracker-client --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index ae0f69e5..ccc383ff 100755 --- a/README.md +++ b/README.md @@ -109,8 +109,25 @@ To troubleshoot your Bluemix application, use the logs. To see the logs, run: See [CONTRIBUTING](CONTRIBUTING.md). ## Open Source @ IBM + Find more open source projects on the [IBM Github Page](http://ibm.github.io/) +### Privacy Notice + +This node sample web application includes code to track deployments to Bluemix and other Cloud Foundry platforms. The following information is sent to a [Deployment Tracker][deploy_track_url] service on each deployment: + +* Application Name (`application_name`) +* Space ID (`space_id`) +* Application Version (`application_version`) +* Application URIs (`application_uris`) + +This data is collected from the `VCAP_APPLICATION` environment variable in IBM Bluemix and other Cloud Foundry platforms. This data is used by IBM to track metrics around deployments of sample applications to IBM Bluemix. Only deployments of sample applications that include code to ping the Deployment Tracker service will be tracked. + +### Disabling Deployment Tracking + +Deployment tracking can be disabled by removing `require('cf-deployment-tracker-client').track();` from the beginning of the `server.js` file at the root of this repo. + +[deploy_track_url]: https://github.com/cloudant-labs/deployment-tracker [service_url]: http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/tone-analyzer.html [cloud_foundry]: https://github.com/cloudfoundry/cli [getting_started]: http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/getting_started/ From e6be48505d272c995abb179ab3c2702ee3c2bbd1 Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 14:10:09 -0500 Subject: [PATCH 08/14] add travis tests --- .travis.yml | 23 +++++++++++++++++++++++ package.json | 11 +++++++++++ test/test.express.js | 29 +++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 .travis.yml create mode 100644 test/test.express.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..49d69352 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,23 @@ +language: node_js +sudo: true +node_js: +- stable +script: +- npm test +env: + global: + - CF_APP=tone-analyzer-demo + - CF_API=https://api.ng.bluemix.net + - CF_ORGANIZATION=WatsonPlatformServices + - CF_SPACE=demos +before_deploy: npm install -g cf-blue-green +deploy: + provider: script + script: + - cf-blue-green-travis + on: + branch: master + repo: watson-developer-cloud/tone-analyzer-nodejs + skip_cleanup: true +notifications: + email: false diff --git a/package.json b/package.json index 4067f9a4..fd84550a 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,9 @@ }, "scripts": { "start": "node server.js", + "test": "npm run jshint && (npm run codecov || true)", + "jshint": "jshint --exclude ./node_modules/", + "codecov": "istanbul cover ./node_modules/mocha/bin/_mocha && codecov" }, "dependencies": { "body-parser": "^1.13.2", @@ -40,5 +43,13 @@ "express-secure-only": "^0.2.1", "helmet": "^1.3.0", "watson-developer-cloud": "^1.2.5" + }, + "devDependencies": { + "codecov": "^1.0.1", + "istanbul": "^0.4.2", + "jshint": "^2.9.1", + "mocha": "^2.4.5", + "nock": "7.7.0", + "supertest": "^1.2.0" } } diff --git a/test/test.express.js b/test/test.express.js new file mode 100644 index 00000000..2c9f46a3 --- /dev/null +++ b/test/test.express.js @@ -0,0 +1,29 @@ +/** + * Copyright 2015 IBM Corp. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +var app = require('../app'); +var request = require('supertest'); +var nock = require('nock'); + +describe('express', function() { + + it('load home page when GET /', function(done) { + request(app).get('/').expect(200, done); + }); + +}); From a41a6526514441111dedbfdde69e7e7a53ce5b6e Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 14:45:27 -0500 Subject: [PATCH 09/14] trigger travis --- server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server.js b/server.js index 251977bd..3efd3865 100644 --- a/server.js +++ b/server.js @@ -10,6 +10,7 @@ require('cf-deployment-tracker-client').track(); var server = require('./app'); var port = process.env.PORT || process.env.VCAP_APP_PORT || 3000; + server.listen(port, function () { console.log('Server running on port: %d', port); }); From cf1b2a860e0cc80510b0b5b81223db1117b2158b Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Wed, 20 Apr 2016 15:47:53 -0500 Subject: [PATCH 10/14] add credentials to travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 49d69352..bec59a05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,8 @@ env: - CF_API=https://api.ng.bluemix.net - CF_ORGANIZATION=WatsonPlatformServices - CF_SPACE=demos + - secure: "1ArUhDyjOH/g7MdGNRCDrDintTMPk1bihDB7ZjTv9p+nxQS090r8VtnkeQgo+yzaK8HHLiG14LFiaWK6eIVf6HnlgyeX3Hh7KsF/rnb0w7TPbPvYpolmDHyLB7FdWtLVVTZPVUpxkiJID6PEh/ENSnC1GWDGpIn9LlyElmVt5sMZAXqs77XJNT0ogxHz1OjZB7UqWwsEPrNmdPEPGkRloxcDdM3m19VCmwL/WoI1a1T9r48L7p8IeM5bQ+olIWnNzoboOw2O+gEUzzHeE8ufXp9eWSju6fO8JCPkNLsGMpVwR8aIoFvOcZPE5W7UfzAeQkYwuayDndqg+lFZd32+tFMr8e6OT590B1fI8Ut9F4cRkGG5ivV16/SJJKrWRp0vRiGZ/N7yCbW+YE2OcsxquXDt5VqRPqW+nAjMCw7ADxq5C3zBMxQK9ST1p0pTVJLLrIq0QUjfYhTEjYufeWaxLXgVdyXE6QLm1Z2REjXLBzUs8Wc1AkJbbhfJ03RJvj39A3dlNgy8F5UbC3AVAQ817xaRPcho4LakfDulTvUooIL0j5ROh81Q/d/DDlnrs4ymlsGqNmJ7ZfMxvtXDesFyy+ZlqmxxRTA8NOpzBMSHP4GZ9oq+HMudPyVVaZexSewouBXj6bOG0uNG8iWa8YCKDnlxiNAmCEEodcLlb+XEhVQ=" + - secure: "bFhB3yakclo4ebxm63JN2BBAptN/UI/OrIBMqeK0a6AufHekbwJWxPjtt3yqruKnop1aLfkTi8MF8C8eQOp8NZ8oVRBzjGmv3h+cTFD9cgcig7Ut0660/TwABIJv8rRMTaOy3CxsRKAVFjMnFFx6YWbKu1+T+5EUfjIiXALzEVOfAr67Y1aR6ACApS9GlUJ2PDErdQVcm6JJ81h/TLLOmmnUoTGv/5O+OUUxzwwLeW+f5jMVgoIUfN9+z1SWzPkBdZhHT91KeihPl1GgBeonBWpCQMGbCuEbB97K0BrbExvZXjqcs4avJr/u2SIOP9NFcw69O59ey5LTBNhW3PcMDDtGFiQ5fjCjP9ldWSnBXYcVd3V9FatX/KnHOE8GtXzCVZt3W3cMnL0s/9wfhfkBuuZscKE8hbKbcMXe9Xtc1Qik8hefCmCWek3utFtW2mLklVo9Y3Ec+p7h7cq7k1LI6zCxHolAGXBu2fXoF6ErJKW1Y8WB4b6EJnpb+XUUgBmw8yZDVDdTKONYDg+EgEqUYB4kzSbvfgH6i8A9nb6rSY3qJUJoj+q5h/EBAxtFz4YEb6QVrT3gkE8acnYRgAKTukX5t5uwO1B7svBaWjZvxfaTBx0GSQmTMNXThgM62ExKEEfkZr5i9Dgu83pGXBEyGS9T+p6gHziE8bZfvU9SWK8=" before_deploy: npm install -g cf-blue-green deploy: provider: script From 999f1273bacc56aee65b4e764f8569cd475d2ca4 Mon Sep 17 00:00:00 2001 From: JAMES ZHANG Date: Thu, 21 Apr 2016 15:16:56 -0500 Subject: [PATCH 11/14] trigger travis --- server.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server.js b/server.js index 3efd3865..251977bd 100644 --- a/server.js +++ b/server.js @@ -10,7 +10,6 @@ require('cf-deployment-tracker-client').track(); var server = require('./app'); var port = process.env.PORT || process.env.VCAP_APP_PORT || 3000; - server.listen(port, function () { console.log('Server running on port: %d', port); }); From 884286cf31f628678e3b1132dbc63c025fae682c Mon Sep 17 00:00:00 2001 From: German Attanasio Ruiz Date: Sat, 23 Apr 2016 13:54:58 -0400 Subject: [PATCH 12/14] Update README.md Added badges to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ccc383ff..6ce022b0 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # Tone Analyzer Node.js Starter Application +[![Build Status](https://travis-ci.org/watson-developer-cloud/tone-analyzer-nodejs.svg?branch=master)](http://travis-ci.org/watson-developer-cloud/tone-analyzer-nodejs) +[![codecov.io](https://codecov.io/github/watson-developer-cloud/tone-analyzer-nodejs/coverage.svg?branch=master)](https://codecov.io/github/watson-developer-cloud/tone-analyzer-nodejs?branch=master) The IBM Watson [Tone Analyzer][service_url] service is a cognitive linguistic analysis service that detects three types of tones from written text: emotions, social tendencies, and writing style. Emotions identified include things like anger, fear, joy, sadness, and disgust. Identified social tendencies include things from the Big Five personality traits used by some psychologists. These include openness, conscientiousness, extraversion, agreeableness, and neuroticism. Identified writing styles include confident, analytical, and tentative. From c82fd732b933ffefe1f444445afb53620edfe481 Mon Sep 17 00:00:00 2001 From: German Attanasio Ruiz Date: Sun, 24 Apr 2016 01:55:23 -0400 Subject: [PATCH 13/14] added 1 instance to manifest.yml --- manifest.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/manifest.yml b/manifest.yml index 618d02d8..6ea0734a 100644 --- a/manifest.yml +++ b/manifest.yml @@ -9,7 +9,5 @@ applications: name: tone-analyzer-demo command: node app.js path: . - memory: 512MB - env: - NODE_ENV: production - SECURE_EXPRESS: 1 \ No newline at end of file + instances: 2 + memory: 512MB \ No newline at end of file From f560413b05e40038a9334048a0a53762a5b2710f Mon Sep 17 00:00:00 2001 From: German Attanasio Ruiz Date: Sun, 24 Apr 2016 01:57:44 -0400 Subject: [PATCH 14/14] update node start command --- manifest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.yml b/manifest.yml index 6ea0734a..b3e762f5 100644 --- a/manifest.yml +++ b/manifest.yml @@ -7,7 +7,7 @@ applications: - services: - tone-analyzer-service name: tone-analyzer-demo - command: node app.js + command: npm start path: . instances: 2 memory: 512MB \ No newline at end of file