diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0d1c2a7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +test/ + +node_modules/ +.git/ +coverage/ +npm-debug.log + +.dockerignore +Dockerfile + +.gitignore +.gitattributes +.editorconfig +.idea/ +*.md +*.iml diff --git a/.gitignore b/.gitignore index 2981ae5..268d94a 100755 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,17 @@ .DS_Store -node_modules -public -.tmp +/node_modules +/public +/.tmp +/tmp .sass-cache -app/bower_components -heroku +/app/bower_components /views -dist -.idea +/dist +/.idea newrelic_agent.log .c9 mongodb +*.log .env .env-prod +npm-debug.log.* diff --git a/.nvmrc b/.nvmrc index 8ac28bf..6b9255c 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -4.6.1 +6.9.2 diff --git a/Gruntfile.js b/Gruntfile.js index c7cffc8..c3124c9 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -282,7 +282,6 @@ module.exports = function (grunt) { src: [ 'package.json', 'server.js', - 'newrelic.js', 'lib/**/*' ] }] @@ -352,7 +351,7 @@ module.exports = function (grunt) { grunt.registerTask('serve', function (target) { if (target === 'dist') { - return grunt.task.run(['build', 'express:prod', 'open', 'express-keepalive']); + return grunt.task.run(['build', 'express:prod', 'express-keepalive']); } grunt.task.run([ diff --git a/app.yaml b/app.yaml new file mode 100644 index 0000000..80eef9d --- /dev/null +++ b/app.yaml @@ -0,0 +1,15 @@ +runtime: nodejs +env: flex +handlers: +- url: /.* + script: IGNORED +endpoints_api_service: + name: api.gdgx.io + config_id: 2017-03-18r0 +network: + instance_tag: https-server + name: gdg-x +automatic_scaling: + min_num_instances: 1 + max_num_instances: 2 + cool_down_period_sec: 300 diff --git a/cron.yaml b/cron.yaml new file mode 100644 index 0000000..7276ce1 --- /dev/null +++ b/cron.yaml @@ -0,0 +1,4 @@ +cron: +- description: daily 9am EST ingestion job + url: / + schedule: every day 13:00 diff --git a/lib/config/express.js b/lib/config/express.js index 8906900..b57158f 100755 --- a/lib/config/express.js +++ b/lib/config/express.js @@ -13,6 +13,7 @@ var errorhandler = require('errorhandler'); var morgan = require('morgan'); var compression = require('compression'); var bodyParser = require('body-parser'); +var yesHttps = require('yes-https'); const MongoStore = require('connect-mongo')(session); /** @@ -73,4 +74,11 @@ module.exports = function (app) { // Passport app.use(passport.initialize()); app.use(passport.session()); + + // Configure GAE proxy and health checks. Force HTTPS. + app.enable('trust proxy'); + app.use(yesHttps({ maxAge: 31536000, includeSubdomains: true, preload: true })); + app.get('/_ah/health', (req, res) => { + res.sendStatus(200); + }); }; diff --git a/openapi.json b/openapi.json new file mode 100644 index 0000000..a23b2df --- /dev/null +++ b/openapi.json @@ -0,0 +1,131 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "GDG-X Hub API", + "description": "API for using data from the Google Developer Groups (GDG) Hub.", + "license": { + "name": "MIT" + }, + "contact": { + "name": "GDG-X Support", + "email": "support@gdgx.io" + } + }, + "host": "api.gdgx.io", + "basePath": "/api/v1", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "paths": { + "/chapters": { + "get": { + "operationId": "listChapters", + "description": "Returns a list containing all Chapters", + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/ChapterList" + } + } + } + } + } + }, + "definitions": { + "ChapterList": { + "type": "object", + "properties": { + "count": { + "type": "number" + }, + "pages": { + "type": "number" + }, + "page": { + "type": "number" + }, + "perpage": { + "type": "number" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/Chapter" + } + } + } + }, + "Chapter": { + "type": "object", + "properties": { + "_id": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "site": { + "type": "string" + }, + "group_type": { + "type": "string" + }, + "country": { + "type": "string" + }, + "state": { + "type": "string" + }, + "city": { + "type": "string" + }, + "name": { + "type": "string" + }, + "__v": { + "type": "number" + }, + "organizers": { + "type": "array", + "items": { + "type": "string" + } + }, + "geo": { + "$ref": "#/definitions/Location" + } + } + }, + "Location": { + "type": "object", + "required": [ + "lng", "lat" + ], + "properties": { + "lng": { + "type": "number" + }, + "lat": { + "type": "number" + } + } + } + }, + "security": [ + + ], + "securityDefinitions": { + + } +} diff --git a/package.json b/package.json index 75a749b..9d75d32 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "dependencies": { "async": "1.4.2", "body-parser": "1.17.1", + "bower": "1.8.0", "burrito": "0.2.12", "cacher": "1.0.0", "cheerio": "0.19.0", @@ -34,32 +35,10 @@ "express": "4.15.2", "express-rate": "0.0.1", "express-session": "1.15.1", + "jpegtran-bin": "0.2.0", + "jshint-stylish": "2.2.1", "google-oauth-jwt": "0.1.7", "googleapis": "0.8.0", - "lodash": "2.4.1", - "method-override": "2.3.7", - "methods": "1.1.2", - "moment": "2.10.6", - "mongoose": "3.5.5", - "morgan": "1.8.1", - "node-forge": "0.6.34", - "node-geocoder": "2.2.0", - "node-uuid": "1.4.3", - "nodemailer": "1.4.0", - "passport": "0.3.2", - "passport-http-bearer": "1.0.1", - "passport-http-oauth": "0.1.3", - "passport-localapikey": "0.0.3", - "serve-favicon": "2.4.1", - "slugify": "0.1.1", - "socket.io": "0.9.17", - "superagent": "0.17.0", - "superagent-retry": "0.3.0", - "timequeue": "0.2.2" - }, - "devDependencies": { - "bower": "1.7.9", - "connect-livereload": "0.6.0", "grunt": "0.4.5", "grunt-autoprefixer": "0.4.0", "grunt-bower-install": "0.7.0", @@ -85,10 +64,35 @@ "grunt-rev": "0.1.0", "grunt-svgmin": "0.2.0", "grunt-usemin": "2.0.0", - "jasmine-core": "2.4.1", - "jpegtran-bin": "0.2.0", - "jshint-stylish": "2.2.1", "karma": "1.2.0", + "load-grunt-tasks": "0.2.0", + "lodash": "2.4.1", + "method-override": "2.3.7", + "methods": "1.1.2", + "moment": "2.10.6", + "mongoose": "3.5.5", + "morgan": "1.8.1", + "node-forge": "0.6.34", + "node-geocoder": "2.2.0", + "node-uuid": "1.4.3", + "nodemailer": "1.4.0", + "passport": "0.3.2", + "passport-http-bearer": "1.0.1", + "passport-http-oauth": "0.1.3", + "passport-localapikey": "0.0.3", + "requirejs": "2.1.20", + "serve-favicon": "2.4.1", + "slugify": "0.1.1", + "socket.io": "0.9.17", + "superagent": "0.17.0", + "superagent-retry": "0.3.0", + "timequeue": "0.2.2", + "time-grunt": "0.2.10", + "yes-https": "0.0.3" + }, + "devDependencies": { + "connect-livereload": "0.6.0", + "jasmine-core": "2.4.1", "karma-chrome-launcher": "2.0.0", "karma-coverage": "1.1.1", "karma-firefox-launcher": "1.0.0", @@ -100,20 +104,17 @@ "karma-phantomjs-launcher": "1.0.1", "karma-requirejs": "1.0.0", "karma-script-launcher": "1.0.0", - "load-grunt-tasks": "0.2.0", - "phantomjs-prebuilt": "2.1.7", - "requirejs": "2.1.20", - "time-grunt": "0.2.10" + "phantomjs-prebuilt": "2.1.7" }, "engines": { - "node": ">=0.12.0" + "node": ">=6" }, "scripts": { - "postinstall": "bower install", - "prestart": "grunt", - "start": "grunt serve", - "startProd": "grunt serve:dist", - "configProd": "sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000;export PORT=3000;", + "deploy": "gcloud app deploy --project gdgx-cloud --no-promote", + "deploy-promote": "gcloud app deploy --project gdgx-cloud", + "deploy-api": "gcloud service-management deploy openapi.json --project gdgx-cloud", + "start": "grunt serve:dist", + "startDev": "grunt serve", "test": "grunt test" } }