{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/comments/31049894","id":31049894,"diff_hunk":"@@ -0,0 +1,160 @@\n+#!/usr/bin/env node\n+\n+/* This Source Code Form is subject to the terms of the Mozilla Public\n+ * License, v. 2.0. If a copy of the MPL was not distributed with this\n+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n+\n+'use strict';\n+\n+var url = require('url');\n+var mozlog = require('mozlog');\n+var request = require('request');\n+var p = require('bluebird');\n+\n+var config = require('../lib/configuration');\n+mozlog.config(config.get('logging'));\n+\n+var logger = require('mozlog')('server.basketproxy');\n+\n+var express = require('express');\n+var bodyParser = require('body-parser');\n+var cors = require('cors');\n+\n+var CORS_ORIGIN = config.get('public_url');\n+var API_KEY = config.get('basket.api_key');\n+var API_URL = config.get('basket.api_url');\n+var VERIFY_URL = config.get('oauth_url') + '/v1/verify';\n+\n+// Verify an OAuth token and return the associated credentials\n+function verifyOAuthToken(cb) {\n+  return function (req, res, next) {\n+    var authHeader = req.headers && req.headers.authorization;\n+\n+    if (! authHeader) {\n+      logger.error('unauthorized');\n+      return next(new Error('Not authorized'));\n+    }\n+\n+    var token = authHeader.replace(/^Bearer /, '');\n+\n+    request.post({\n+      url: VERIFY_URL,\n+      json: {\n+        token: token\n+      }\n+    }, function (err, _, body) {\n+      // TODO use an actual error format\n+      if (err) {\n+        logger.error('auth.error', err);\n+        res.status(400).send(err);\n+        return;\n+      }\n+\n+      if (body.code >= 400) {\n+        logger.error('unauthorized', body);\n+        res.status(400).send('unauthorized');\n+        return;\n+      }\n+\n+      logger.debug('auth.valid', body);\n+\n+      cb(body, req, res, next);\n+    });\n+  };\n+}\n+\n+// Send a request to the Basket backend\n+function basketRequest(path, method, params) {\n+  var config = {\n+    url: API_URL + path,\n+    strictSSL: true,\n+    method: method,\n+    headers: {\n+      'X-API-Key': API_KEY\n+    },\n+    form: params\n+  };\n+\n+  var deferred = p.defer();\n+\n+  request(config, function (err, httpRequest, body) {\n+    if (err) {\n+      logger.error('basket.error', err);\n+      return deferred.reject(err);\n+    }\n+\n+    if (httpRequest.statusCode !== 200) {\n+      // TODO do something here.\n+    }\n+\n+    deferred.resolve(body);\n+  });\n+\n+  return deferred.promise;\n+}\n+\n+function forwardBasketResponse(res, path, method, params) {\n+  return basketRequest(path, method, params)\n+    .then(function (body) {\n+      res.type('application/json');\n+      res.send(body);\n+    }, function (err) {\n+      res.status(400).send(err);\n+    });\n+}\n+\n+function initApp() {\n+  var app = express();\n+  app.use(bodyParser.json());\n+\n+  app.use(cors({\n+    origin: CORS_ORIGIN\n+  }));\n+\n+  app.get('/lookup-user', verifyOAuthToken(function (creds, req, res) {\n+    forwardBasketResponse(res, '/lookup-user/?email=' + creds.email, 'get');\n+  }));\n+\n+  app.post('/subscribe', verifyOAuthToken(function (creds, req, res) {\n+    // Basket is slow, don't wait around for its response.\n+    res.json({ status: 'ok' });\n+\n+    basketRequest('/subscribe/', 'post', {\n+      email: creds.email,\n+      newsletters: req.body.newsletters.join(','),\n+      optin: 'Y'\n+    });\n+  }));\n+\n+  app.post('/unsubscribe', verifyOAuthToken(function (creds, req, res) {\n+    // Basket is slow, don't wait around for its response.\n+    res.json({ status: 'ok' });\n+\n+    basketRequest('/lookup-user/?email=' + creds.email, 'get')\n+      .then(function (body) {\n+        var token;\n+        try {\n+          token = JSON.parse(body).token;\n+        } catch(e) {\n+          return res.status(400).send('error');\n+        }\n+\n+        basketRequest('/unsubscribe/' + token + '/', 'post', {\n+          email: creds.email,\n+          newsletters: req.body.newsletters.join(',')\n+        });\n+      });\n+  }));\n+\n+  return app;\n+}\n+\n+function listen(app) {\n+  var serverUrl = url.parse(config.get('marketing_email.api_url'));\n+  app.listen(serverUrl.port, serverUrl.hostname);\n+  logger.info('FxA Basket Proxy listening on port', serverUrl.port);","path":"server/bin/basket-proxy-server.js","position":155,"original_position":155,"commit_id":"b830810e31a7a8e604514b18f11562c21b674af2","original_commit_id":"b830810e31a7a8e604514b18f11562c21b674af2","user":{"login":"vladikoff","id":128755,"avatar_url":"https://avatars.githubusercontent.com/u/128755?v=3","gravatar_id":"","url":"https://api.github.com/users/vladikoff","html_url":"https://github.com/vladikoff","followers_url":"https://api.github.com/users/vladikoff/followers","following_url":"https://api.github.com/users/vladikoff/following{/other_user}","gists_url":"https://api.github.com/users/vladikoff/gists{/gist_id}","starred_url":"https://api.github.com/users/vladikoff/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vladikoff/subscriptions","organizations_url":"https://api.github.com/users/vladikoff/orgs","repos_url":"https://api.github.com/users/vladikoff/repos","events_url":"https://api.github.com/users/vladikoff/events{/privacy}","received_events_url":"https://api.github.com/users/vladikoff/received_events","type":"User","site_admin":false},"body":"Could we log which server it is proxying to here.","created_at":"2015-05-26T15:59:47Z","updated_at":"2015-05-26T15:59:47Z","html_url":"https://github.com/mozilla/fxa-content-server/pull/2452#discussion_r31049894","pull_request_url":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/2452","_links":{"self":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/comments/31049894"},"html":{"href":"https://github.com/mozilla/fxa-content-server/pull/2452#discussion_r31049894"},"pull_request":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/2452"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/2452","id":35921696,"html_url":"https://github.com/mozilla/fxa-content-server/pull/2452","diff_url":"https://github.com/mozilla/fxa-content-server/pull/2452.diff","patch_url":"https://github.com/mozilla/fxa-content-server/pull/2452.patch","issue_url":"https://api.github.com/repos/mozilla/fxa-content-server/issues/2452","number":2452,"state":"open","locked":false,"title":"WIP: Start on the email opt-in.","user":{"login":"shane-tomlinson","id":848085,"avatar_url":"https://avatars.githubusercontent.com/u/848085?v=3","gravatar_id":"","url":"https://api.github.com/users/shane-tomlinson","html_url":"https://github.com/shane-tomlinson","followers_url":"https://api.github.com/users/shane-tomlinson/followers","following_url":"https://api.github.com/users/shane-tomlinson/following{/other_user}","gists_url":"https://api.github.com/users/shane-tomlinson/gists{/gist_id}","starred_url":"https://api.github.com/users/shane-tomlinson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shane-tomlinson/subscriptions","organizations_url":"https://api.github.com/users/shane-tomlinson/orgs","repos_url":"https://api.github.com/users/shane-tomlinson/repos","events_url":"https://api.github.com/users/shane-tomlinson/events{/privacy}","received_events_url":"https://api.github.com/users/shane-tomlinson/received_events","type":"User","site_admin":false},"body":"ref #2443 ","created_at":"2015-05-21T10:52:52Z","updated_at":"2015-05-26T15:59:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0555cd83176316089c5538d6d7198fd52ad75812","assignee":null,"milestone":{"url":"https://api.github.com/repos/mozilla/fxa-content-server/milestones/48","html_url":"https://github.com/mozilla/fxa-content-server/milestones/train%2038","labels_url":"https://api.github.com/repos/mozilla/fxa-content-server/milestones/48/labels","id":1044666,"number":48,"title":"train 38","description":"Train 37 - May 12-May 25","creator":{"login":"shane-tomlinson","id":848085,"avatar_url":"https://avatars.githubusercontent.com/u/848085?v=3","gravatar_id":"","url":"https://api.github.com/users/shane-tomlinson","html_url":"https://github.com/shane-tomlinson","followers_url":"https://api.github.com/users/shane-tomlinson/followers","following_url":"https://api.github.com/users/shane-tomlinson/following{/other_user}","gists_url":"https://api.github.com/users/shane-tomlinson/gists{/gist_id}","starred_url":"https://api.github.com/users/shane-tomlinson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shane-tomlinson/subscriptions","organizations_url":"https://api.github.com/users/shane-tomlinson/orgs","repos_url":"https://api.github.com/users/shane-tomlinson/repos","events_url":"https://api.github.com/users/shane-tomlinson/events{/privacy}","received_events_url":"https://api.github.com/users/shane-tomlinson/received_events","type":"User","site_admin":false},"open_issues":6,"closed_issues":11,"state":"open","created_at":"2015-03-30T12:54:05Z","updated_at":"2015-05-26T13:48:32Z","due_on":"2015-05-26T04:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/2452/commits","review_comments_url":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/2452/comments","review_comment_url":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla/fxa-content-server/issues/2452/comments","statuses_url":"https://api.github.com/repos/mozilla/fxa-content-server/statuses/b830810e31a7a8e604514b18f11562c21b674af2","head":{"label":"mozilla:issue-2443-email-opt-in","ref":"issue-2443-email-opt-in","sha":"b830810e31a7a8e604514b18f11562c21b674af2","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":11778024,"name":"fxa-content-server","full_name":"mozilla/fxa-content-server","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/fxa-content-server","description":"Firefox Accounts Content Server","fork":false,"url":"https://api.github.com/repos/mozilla/fxa-content-server","forks_url":"https://api.github.com/repos/mozilla/fxa-content-server/forks","keys_url":"https://api.github.com/repos/mozilla/fxa-content-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/fxa-content-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/fxa-content-server/teams","hooks_url":"https://api.github.com/repos/mozilla/fxa-content-server/hooks","issue_events_url":"https://api.github.com/repos/mozilla/fxa-content-server/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/fxa-content-server/events","assignees_url":"https://api.github.com/repos/mozilla/fxa-content-server/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/fxa-content-server/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/fxa-content-server/tags","blobs_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/fxa-content-server/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/fxa-content-server/languages","stargazers_url":"https://api.github.com/repos/mozilla/fxa-content-server/stargazers","contributors_url":"https://api.github.com/repos/mozilla/fxa-content-server/contributors","subscribers_url":"https://api.github.com/repos/mozilla/fxa-content-server/subscribers","subscription_url":"https://api.github.com/repos/mozilla/fxa-content-server/subscription","commits_url":"https://api.github.com/repos/mozilla/fxa-content-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/fxa-content-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/fxa-content-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/fxa-content-server/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/fxa-content-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/fxa-content-server/merges","archive_url":"https://api.github.com/repos/mozilla/fxa-content-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/fxa-content-server/downloads","issues_url":"https://api.github.com/repos/mozilla/fxa-content-server/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/fxa-content-server/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/fxa-content-server/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/fxa-content-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/fxa-content-server/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/fxa-content-server/releases{/id}","created_at":"2013-07-30T23:35:35Z","updated_at":"2015-05-20T17:56:21Z","pushed_at":"2015-05-26T14:23:02Z","git_url":"git://github.com/mozilla/fxa-content-server.git","ssh_url":"git@github.com:mozilla/fxa-content-server.git","clone_url":"https://github.com/mozilla/fxa-content-server.git","svn_url":"https://github.com/mozilla/fxa-content-server","homepage":"","size":26207,"stargazers_count":65,"watchers_count":65,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":40,"mirror_url":null,"open_issues_count":204,"forks":40,"open_issues":204,"watchers":65,"default_branch":"master"}},"base":{"label":"mozilla:master","ref":"master","sha":"492f8bbfd77666e97e93a0e40fb3efa309d28fc5","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":11778024,"name":"fxa-content-server","full_name":"mozilla/fxa-content-server","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/fxa-content-server","description":"Firefox Accounts Content Server","fork":false,"url":"https://api.github.com/repos/mozilla/fxa-content-server","forks_url":"https://api.github.com/repos/mozilla/fxa-content-server/forks","keys_url":"https://api.github.com/repos/mozilla/fxa-content-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/fxa-content-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/fxa-content-server/teams","hooks_url":"https://api.github.com/repos/mozilla/fxa-content-server/hooks","issue_events_url":"https://api.github.com/repos/mozilla/fxa-content-server/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/fxa-content-server/events","assignees_url":"https://api.github.com/repos/mozilla/fxa-content-server/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/fxa-content-server/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/fxa-content-server/tags","blobs_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/fxa-content-server/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/fxa-content-server/languages","stargazers_url":"https://api.github.com/repos/mozilla/fxa-content-server/stargazers","contributors_url":"https://api.github.com/repos/mozilla/fxa-content-server/contributors","subscribers_url":"https://api.github.com/repos/mozilla/fxa-content-server/subscribers","subscription_url":"https://api.github.com/repos/mozilla/fxa-content-server/subscription","commits_url":"https://api.github.com/repos/mozilla/fxa-content-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/fxa-content-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/fxa-content-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/fxa-content-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/fxa-content-server/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/fxa-content-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/fxa-content-server/merges","archive_url":"https://api.github.com/repos/mozilla/fxa-content-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/fxa-content-server/downloads","issues_url":"https://api.github.com/repos/mozilla/fxa-content-server/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/fxa-content-server/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/fxa-content-server/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/fxa-content-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/fxa-content-server/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/fxa-content-server/releases{/id}","created_at":"2013-07-30T23:35:35Z","updated_at":"2015-05-20T17:56:21Z","pushed_at":"2015-05-26T14:23:02Z","git_url":"git://github.com/mozilla/fxa-content-server.git","ssh_url":"git@github.com:mozilla/fxa-content-server.git","clone_url":"https://github.com/mozilla/fxa-content-server.git","svn_url":"https://github.com/mozilla/fxa-content-server","homepage":"","size":26207,"stargazers_count":65,"watchers_count":65,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":40,"mirror_url":null,"open_issues_count":204,"forks":40,"open_issues":204,"watchers":65,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/2452"},"html":{"href":"https://github.com/mozilla/fxa-content-server/pull/2452"},"issue":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/issues/2452"},"comments":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/issues/2452/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/2452/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/pulls/2452/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/fxa-content-server/statuses/b830810e31a7a8e604514b18f11562c21b674af2"}}}}