{"action":"created","comment":{"url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/comments/60991554","id":60991554,"diff_hunk":"@@ -0,0 +1,153 @@\n+/*\n+ * Copyright 2016 Google Inc. All rights reserved.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except\n+ * in compliance with the License. You may obtain a copy of the License at\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software distributed under the License\n+ * is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\n+ * or implied. See the License for the specific language governing permissions and limitations under\n+ * the License.\n+ */\n+\n+/// <reference path=\"../../../externs/ts/node/node.d.ts\" />\n+/// <reference path=\"../../../externs/ts/request/request.d.ts\" />\n+/// <reference path=\"../../../externs/ts/googleapis/googleapis.d.ts\" />\n+/// <reference path=\"common.d.ts\" />\n+\n+import childProcess = require('child_process');\n+import fs = require('fs');\n+import google = require('googleapis');\n+import http = require('http');\n+import logging = require('./logging');\n+\n+\n+var oauth2Client: any = undefined;\n+\n+// These are the gcloud credentials and are not actually secret.\n+let clientId = '32555940559.apps.googleusercontent.com';\n+let clientSecret = 'ZmssLNjJy2998hD4CTg2ejr2';\n+let gcloudDir = process.env.CLOUDSDK_CONFIG || '/root/.config/gcloud';\n+let userCredFile = gcloudDir + '/credentials';\n+let appCredFile = process.env.GOOGLE_APPLICATION_CREDENTIALS || (gcloudDir + '/application_default_credentials.json')\n+\n+let scopes = [\n+  'https://www.googleapis.com/auth/userinfo.email',\n+  //'https://www.googleapis.com/auth/userinfo.profile',\n+  'https://www.googleapis.com/auth/cloud-platform',\n+];\n+\n+/**\n+ * Take a id_token_id and decode it. These are base64 but with the some character substitutions and the\n+ * trailing '='s removed, so we first revert those and then run through base64 decoding.\n+ */\n+function base64decodeSegment(str: string) {\n+  str += Array(5 - str.length % 4).join('=');\n+  str= str.replace(/\\-/g, '+').replace(/_/g, '/');\n+  return new Buffer(str, 'base64').toString();\n+}\n+\n+/**\n+ * Save the tokens in a credentials file that Datalab and gcloud can both use.\n+ */\n+function persistCredentials(tokens: any) {\n+  if (!fs.existsSync(gcloudDir)) {\n+    fs.mkdirSync(gcloudDir);\n+  }\n+  fs.writeFileSync(appCredFile,\n+      JSON.stringify({\n+        client_id: clientId,\n+        client_secret: clientSecret,\n+        refresh_token: tokens.refresh_token,\n+        type: \"authorized_user\"\n+      })\n+  );\n+  var segments = tokens.id_token.split('.');\n+  var payload = JSON.parse(base64decodeSegment(segments[1]));\n+  fs.writeFileSync(userCredFile,\n+      JSON.stringify({\n+        data:\n+            [\n+              {\n+                credential: {\n+                  _class: \"OAuth2Credentials\",\n+                  _module: \"oauth2client.client\",\n+                  access_token: tokens.access_token,\n+                  client_id: clientId,\n+                  client_secret: clientSecret,\n+                  id_token: payload,\n+                  invalid: false,\n+                  refresh_token: tokens.refresh_token,\n+                  revoke_uri: \"https://accounts.google.com/o/oauth2/revoke\",\n+                  token_expiry: (new Date(tokens.expiry_date)).toISOString(),\n+                  token_response: {\n+                    access_token: tokens.access_token,\n+                    expires_in: 3600,\n+                    id_token: tokens.id_token,\n+                    refresh_token: tokens.refresh_token,\n+                    token_type: \"Bearer\"\n+                  },\n+                  token_uri: \"https://accounts.google.com/o/oauth2/token\",\n+                  user_agent: \"Cloud SDK Command Line Tool\"\n+                },\n+                key: {\n+                  account: payload.email,\n+                  type: \"google-cloud-sdk\"\n+                }\n+              }\n+            ],\n+        file_version: 1\n+      })\n+  );\n+  // Tell gcloud which account we are using.\n+  childProcess.exec('gcloud config set account ' + payload.email, {env: process.env}, function(err, stdout, stderr) {\n+    if (err) {\n+      logging.getLogger().error(err, 'Failed to set gcloud account. stderr: %s', stderr);\n+      return;\n+    }\n+  });\n+}\n+\n+export function handleAuthFlow(request: http.ServerRequest, response: http.ServerResponse, parsed_url: any): boolean {\n+  var path = parsed_url.pathname;\n+  if (path.indexOf('/oauthcallback') == 0) {  // Return from auth flow.\n+    var query = parsed_url.query;\n+    if (query.code) {\n+      oauth2Client.getToken(query.code, function (err:any, tokens:any) {\n+        if (err) {\n+          response.writeHead(403);\n+          response.end();\n+        } else {\n+          logging.getLogger().info('Got tokens');\n+          oauth2Client.setCredentials(tokens);\n+          // Push them to Jupyter and handle request.\n+          persistCredentials(tokens);\n+          response.statusCode = 302;\n+          response.setHeader('Location', query.state);\n+          response.end();\n+        }\n+      });\n+    }\n+  } else if (!oauth2Client && process.env.DATALAB_ENV == 'local' && !fs.existsSync(userCredFile)) {","path":"sources/web/datalab/auth.ts","position":133,"original_position":133,"commit_id":"6f6c8e9f4307d44ed9705252b231747b2c8fbff7","original_commit_id":"6f6c8e9f4307d44ed9705252b231747b2c8fbff7","user":{"login":"gramster","id":2762632,"avatar_url":"https://avatars.githubusercontent.com/u/2762632?v=3","gravatar_id":"","url":"https://api.github.com/users/gramster","html_url":"https://github.com/gramster","followers_url":"https://api.github.com/users/gramster/followers","following_url":"https://api.github.com/users/gramster/following{/other_user}","gists_url":"https://api.github.com/users/gramster/gists{/gist_id}","starred_url":"https://api.github.com/users/gramster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gramster/subscriptions","organizations_url":"https://api.github.com/users/gramster/orgs","repos_url":"https://api.github.com/users/gramster/repos","events_url":"https://api.github.com/users/gramster/events{/privacy}","received_events_url":"https://api.github.com/users/gramster/received_events","type":"User","site_admin":false},"body":"Yes","created_at":"2016-04-25T21:20:11Z","updated_at":"2016-04-25T21:20:11Z","html_url":"https://github.com/GoogleCloudPlatform/datalab/pull/804#discussion_r60991554","pull_request_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/804","_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/comments/60991554"},"html":{"href":"https://github.com/GoogleCloudPlatform/datalab/pull/804#discussion_r60991554"},"pull_request":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/804"}}},"pull_request":{"url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/804","id":67561367,"html_url":"https://github.com/GoogleCloudPlatform/datalab/pull/804","diff_url":"https://github.com/GoogleCloudPlatform/datalab/pull/804.diff","patch_url":"https://github.com/GoogleCloudPlatform/datalab/pull/804.patch","issue_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues/804","number":804,"state":"open","locked":false,"title":"Lots of fixes/improvements to auth (and update to Jupyter 4.2)","user":{"login":"gramster","id":2762632,"avatar_url":"https://avatars.githubusercontent.com/u/2762632?v=3","gravatar_id":"","url":"https://api.github.com/users/gramster","html_url":"https://github.com/gramster","followers_url":"https://api.github.com/users/gramster/followers","following_url":"https://api.github.com/users/gramster/following{/other_user}","gists_url":"https://api.github.com/users/gramster/gists{/gist_id}","starred_url":"https://api.github.com/users/gramster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gramster/subscriptions","organizations_url":"https://api.github.com/users/gramster/orgs","repos_url":"https://api.github.com/users/gramster/repos","events_url":"https://api.github.com/users/gramster/events{/privacy}","received_events_url":"https://api.github.com/users/gramster/received_events","type":"User","site_admin":false},"body":"The user can now run with no auth-related environment variables, in which\r\ncase they will need to do auth at start and can then use Datalab and gcloud\r\nwithin Datalab.\r\n\r\nOr they can set GOOGLE_APPLICATION_CREDENTIALS to point to a file (possibly\r\noutside the container if mapped in) and then they may not need to do auth if\r\nthe file already exists (but gcloud won't work).\r\n\r\nOr they can set CLOUDSDK_CONFIG to point to a directory (possibly outside\r\nthe container) in which case they may not need to do auth and gclould will\r\nwork (as the directory is used for both app and user credentials).\r\n\r\nOutside of Datalab they should either use one of the above two env vars or\r\nif they are not in Docker we can kick off an auth flow in the users local\r\nbrowser.\r\n\r\nAlso in this PR: \r\n\r\n- hiding help pane by default.\r\n- removing some unused socket.io code\r\n- some progress towards getting ipywidgets working\r\n- fix 'Convert to Python' menu option\r\n- support opening non-notebook files\r\n- some fixes to the Sphinx docs\r\n","created_at":"2016-04-22T19:32:42Z","updated_at":"2016-04-25T21:20:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b48ec2a06fe34c60f7e708c71ae7c7fd226cdc8d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/804/commits","review_comments_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/804/comments","review_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/comments{/number}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues/804/comments","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/statuses/6f6c8e9f4307d44ed9705252b231747b2c8fbff7","head":{"label":"GoogleCloudPlatform:jupyter42","ref":"jupyter42","sha":"6f6c8e9f4307d44ed9705252b231747b2c8fbff7","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":22693761,"name":"datalab","full_name":"GoogleCloudPlatform/datalab","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/datalab","description":"Interactive tools and developer experiences for Big Data on Google Cloud Platform.","fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/datalab","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues/comments{/number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/releases{/id}","deployments_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/deployments","created_at":"2014-08-06T18:37:34Z","updated_at":"2016-04-24T22:36:31Z","pushed_at":"2016-04-25T02:21:40Z","git_url":"git://github.com/GoogleCloudPlatform/datalab.git","ssh_url":"git@github.com:GoogleCloudPlatform/datalab.git","clone_url":"https://github.com/GoogleCloudPlatform/datalab.git","svn_url":"https://github.com/GoogleCloudPlatform/datalab","homepage":"","size":183822,"stargazers_count":230,"watchers_count":230,"language":"Jupyter Notebook","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":54,"mirror_url":null,"open_issues_count":128,"forks":54,"open_issues":128,"watchers":230,"default_branch":"master"}},"base":{"label":"GoogleCloudPlatform:master","ref":"master","sha":"c59caf3bae92517fd597b635e7fa11083a65a7a1","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":22693761,"name":"datalab","full_name":"GoogleCloudPlatform/datalab","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/datalab","description":"Interactive tools and developer experiences for Big Data on Google Cloud Platform.","fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/datalab","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues/comments{/number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/releases{/id}","deployments_url":"https://api.github.com/repos/GoogleCloudPlatform/datalab/deployments","created_at":"2014-08-06T18:37:34Z","updated_at":"2016-04-24T22:36:31Z","pushed_at":"2016-04-25T02:21:40Z","git_url":"git://github.com/GoogleCloudPlatform/datalab.git","ssh_url":"git@github.com:GoogleCloudPlatform/datalab.git","clone_url":"https://github.com/GoogleCloudPlatform/datalab.git","svn_url":"https://github.com/GoogleCloudPlatform/datalab","homepage":"","size":183822,"stargazers_count":230,"watchers_count":230,"language":"Jupyter Notebook","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":54,"mirror_url":null,"open_issues_count":128,"forks":54,"open_issues":128,"watchers":230,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/804"},"html":{"href":"https://github.com/GoogleCloudPlatform/datalab/pull/804"},"issue":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues/804"},"comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/issues/804/comments"},"review_comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/804/comments"},"review_comment":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/pulls/804/commits"},"statuses":{"href":"https://api.github.com/repos/GoogleCloudPlatform/datalab/statuses/6f6c8e9f4307d44ed9705252b231747b2c8fbff7"}}}}