{"action":"created","comment":{"url":"https://api.github.com/repos/OpenTMI/opentmi/pulls/comments/90703099","pull_request_review_id":11218295,"id":90703099,"diff_hunk":"@@ -115,105 +117,166 @@ var Controller = function(){\n       next();\n     }\n   }\n+  \n   /*\n    |--------------------------------------------------------------------------\n    | Login with GitHub\n    |--------------------------------------------------------------------------\n    */\n-  this.github = function(req, res) {\n+  this.github = function (req, res) {\n     var accessTokenUrl = 'https://github.com/login/oauth/access_token';\n     var userApiUrl = 'https://api.github.com/user';\n-    \n-    var params = {\n-      code: req.body.code,\n-      client_id: req.body.clientId,\n-      client_secret: nconf.get('github').clientSecret,\n-      redirect_uri: req.body.redirectUri\n+\n+    var authorization = function (callback) {\n+      var params = {\n+        code: req.body.code,\n+        client_id: req.body.clientId,\n+        client_secret: nconf.get('github').clientSecret,\n+        redirect_uri: req.body.redirectUri,\n+      };\n+\n+      request.get({ url: accessTokenUrl, qs: params },\n+        function (err, response, accessToken) {\n+          if (err) { callback(err); return; }\n+\n+          accessToken = qs.parse(accessToken);\n+          var headers = { 'User-Agent': 'Satellizer' };\n+\n+          callback(null, accessToken, headers);\n+        });\n     };\n-    console.log(params);\n-    // Step 1. Exchange authorization code for access token.\n-    request.get({ url: accessTokenUrl, \n-                  qs: params \n-                }, function(err, response, accessToken) {\n \n-      accessToken = qs.parse(accessToken);\n-      var headers = { 'User-Agent': 'Satellizer' };\n+    var getProfile = function (accessToken, headers, callback) {\n+      request.get({ url: userApiUrl, qs: accessToken, headers: headers, json: true },\n+        function (err, response, profile) {\n+          if (err) { callback(err); return; }\n \n-      // Step 2. Retrieve profile information about the current user.\n-      request.get({ url: userApiUrl, \n-                    qs: accessToken, \n-                    headers: headers, \n-                    json: true \n-                  }, function(err, response, profile) {\n-\n-        if( response.statusCode != 200  ) {\n-          return res.status(409).json({\n-            message: profile.message\n+          if (response.statusCode !== 200) {\n+            return res.status(409).json({\n+              message: profile.message,\n+            });\n+          }\n+\n+          if (!profile.email) {\n+            return res.status(409).json({\n+              message: 'Did not get email address.',\n+            });\n+          }\n+\n+          callback(null, accessToken, headers, profile);\n+        });\n+    };\n+\n+    var checkOrganization = function (accessToken, headers, profile, callback) {\n+      request.get({ url: userApiUrl + '/orgs', qs: accessToken, headers: headers, json: true },\n+        function (err, response) {\n+          if (err) { callback(err); return; }\n+\n+          var belongsOrg = _.find(response.body, { login: nconf.get('github').organization });\n+\n+          if (belongsOrg) {\n+            callback(null, accessToken, headers, profile);\n+          } else {\n+            return res.status(401).send({\n+              message: 'You do not have required access.',\n+            });\n+          }\n+        });\n+    };\n+\n+    var checkAdmin = function (accessToken, headers, profile, callback) {\n+      request.get({ url: userApiUrl + '/teams', qs: accessToken, headers: headers, json: true },\n+        function (err, response) {\n+          if (err) { callback(err); return; }\n+\n+          var isAdmin = _.find(response.body, function (team) {\n+            return team.name === nconf.get('github').adminTeam && team.organization.login === nconf.get('github').organization;\n           });\n-        }\n-        if( !profile.email ){\n-          console.log(response.headers);\n-          console.log(profile);\n-          return res.status(409).json({\n-            message: 'did not get email address'\n-          }); \n-        }\n-        // Step 3a. Link user accounts.\n-        if (req.headers.authorization ) {\n-          console.log('Link user account')\n-          console.log(profile)\n-          User.findOne({ github: profile.id }, function(err, existingUser) {\n-            if (existingUser) {\n-              console.log(existingUser)\n-              return res.status(409).send({ message: 'There is already a GitHub account that belongs to you' });\n-            }\n-            var token = req.headers.authorization.split(' ')[1];\n-            var payload = jwt.decode(token, config.TOKEN_SECRET);\n-            User.findById(payload.sub, function(err, user) {\n-              if (!user) {\n-                return res.status(400).send({ message: 'User not found' });\n-              }\n-              user.github = profile.id;\n-              user.picture = user.picture || profile.avatar_url;\n-              user.displayName = user.displayName || profile.name;\n-              user.name = user.displayName;\n-              user.email = user.email;\n-              user.save(function(error) {\n-                var token = createJWT(user);\n-                res.send({ token: token });\n-              });\n+          console.log(isAdmin);\n+          profile.role = isAdmin ? 'admin' : 'user';\n+\n+          callback(null, profile);\n+        });\n+    };\n+\n+    var ready = function (err, profile) {\n+      // Helper function to update user's admin group status.\n+      var updateGroup = function (user, done) {\n+        Group.findOne({ users: user, name: 'admins' }, function (err, group) {\n+          if (group && profile.role === 'user') {\n+            user.removeFromGroup('admins', function (user) {\n+              user.save(done);\n             });\n+          } else if (!group && profile.role === 'admin') {\n+            user.addToGroup('admins', function (user) {\n+              user.save(done);\n+            });\n+          } else {\n+            user.save(done);\n+          }\n+        });\n+      };\n+\n+      if (err) {\n+        return res.sendStatus(500);\n+      }\n+\n+      User.findOne({ github: profile.id }, function (err, existingUser) {\n+        // Check if the user account exists.\n+        if (existingUser) {\n+          winston.info('Return an existing user account.');\n+\n+          if (req.headers.authorization) {\n+            return res.status(409).send({ message: 'There is already a GitHub account that belongs to you' });\n+          }\n+\n+          updateGroup(existingUser, function () {\n+            var token = createJWT(existingUser, profile.role);\n+            return res.send({ token: token });\n           });\n-        } else {\n-          console.log('Create a new user account or return an existing one.');\n-          // Step 3b. Create a new user account or return an existing one.\n-          User.findOne({ github: profile.id }, function(err, existingUser) {\n-            if (existingUser) {\n-              var token = createJWT(existingUser);\n-              return res.send({ token: token });\n+        } else if (req.headers.authorization) {\n+          // Check if the user account needs to be created or just linked.\n+          winston.info('Link user account with github account.');\n+          var token = req.headers.authorization.split(' ')[1];\n+          var payload = jwt.decode(token, config.TOKEN_SECRET);\n+          User.findById(payload.sub, function (err, user) {\n+            if (!user) {\n+              return res.status(400).send({ message: 'User not found' });\n             }\n-            var user = new User();\n             user.github = profile.id;\n-            user.picture = profile.avatar_url;\n-            user.displayName = profile.name;\n-            user.email = profile.email;\n-            user.save(function(error) {\n-              console.log(error);\n-              var token = createJWT(user);\n+            user.picture = user.picture || profile.avatar_url;\n+            user.displayName = user.displayName || profile.name;\n+            user.name = user.displayName;\n+            user.email = user.email;\n+            updateGroup(user, function () {\n+              var token = createJWT(user, profile.role);\n               res.send({ token: token });\n             });\n           });\n+        } else {\n+          winston.info('Create a new user account.');\n+          var user = new User();\n+          user.github = profile.id;\n+          user.picture = profile.avatar_url;\n+          user.displayName = profile.name;\n+          user.email = profile.email;\n+\n+          updateGroup(user, function () {\n+            var token = createJWT(user, profile.role);\n+            res.send({ token: token });\n+          });\n         }\n-      });\n-    });\n-  }\n+      }); // End User.findOne()\n+    };","path":"app/controllers/authentication.js","position":254,"original_position":254,"commit_id":"e6d8e669f315194c4deac71ed699c438bc3c2d6b","original_commit_id":"e6d8e669f315194c4deac71ed699c438bc3c2d6b","user":{"login":"jupe","id":3822425,"avatar_url":"https://avatars.githubusercontent.com/u/3822425?v=3","gravatar_id":"","url":"https://api.github.com/users/jupe","html_url":"https://github.com/jupe","followers_url":"https://api.github.com/users/jupe/followers","following_url":"https://api.github.com/users/jupe/following{/other_user}","gists_url":"https://api.github.com/users/jupe/gists{/gist_id}","starred_url":"https://api.github.com/users/jupe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jupe/subscriptions","organizations_url":"https://api.github.com/users/jupe/orgs","repos_url":"https://api.github.com/users/jupe/repos","events_url":"https://api.github.com/users/jupe/events{/privacy}","received_events_url":"https://api.github.com/users/jupe/received_events","type":"User","site_admin":false},"body":"ready() - part seems to be still little kind cb-hell 😄","created_at":"2016-12-02T19:20:37Z","updated_at":"2016-12-02T19:27:21Z","html_url":"https://github.com/OpenTMI/opentmi/pull/13#discussion_r90703099","pull_request_url":"https://api.github.com/repos/OpenTMI/opentmi/pulls/13","_links":{"self":{"href":"https://api.github.com/repos/OpenTMI/opentmi/pulls/comments/90703099"},"html":{"href":"https://github.com/OpenTMI/opentmi/pull/13#discussion_r90703099"},"pull_request":{"href":"https://api.github.com/repos/OpenTMI/opentmi/pulls/13"}}},"pull_request":{"url":"https://api.github.com/repos/OpenTMI/opentmi/pulls/13","id":94816630,"html_url":"https://github.com/OpenTMI/opentmi/pull/13","diff_url":"https://github.com/OpenTMI/opentmi/pull/13.diff","patch_url":"https://github.com/OpenTMI/opentmi/pull/13.patch","issue_url":"https://api.github.com/repos/OpenTMI/opentmi/issues/13","number":13,"state":"open","locked":false,"title":"Inventory changes and additions","user":{"login":"paavoee","id":15650873,"avatar_url":"https://avatars.githubusercontent.com/u/15650873?v=3","gravatar_id":"","url":"https://api.github.com/users/paavoee","html_url":"https://github.com/paavoee","followers_url":"https://api.github.com/users/paavoee/followers","following_url":"https://api.github.com/users/paavoee/following{/other_user}","gists_url":"https://api.github.com/users/paavoee/gists{/gist_id}","starred_url":"https://api.github.com/users/paavoee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paavoee/subscriptions","organizations_url":"https://api.github.com/users/paavoee/orgs","repos_url":"https://api.github.com/users/paavoee/repos","events_url":"https://api.github.com/users/paavoee/events{/privacy}","received_events_url":"https://api.github.com/users/paavoee/received_events","type":"User","site_admin":false},"body":"\r\n- Modified authentication (known issue: hardcoded configs) \r\n- New DB models added (Item, Loan)\r\n- Routes & controllers for new models\r\n- Basic tests\r\n- new way to populate db collections using node-mongo-seeds","created_at":"2016-11-22T13:47:35Z","updated_at":"2016-12-02T19:27:22Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f19891daf8fa68e8616d982713fb3bbded2e4668","assignee":{"login":"jupe","id":3822425,"avatar_url":"https://avatars.githubusercontent.com/u/3822425?v=3","gravatar_id":"","url":"https://api.github.com/users/jupe","html_url":"https://github.com/jupe","followers_url":"https://api.github.com/users/jupe/followers","following_url":"https://api.github.com/users/jupe/following{/other_user}","gists_url":"https://api.github.com/users/jupe/gists{/gist_id}","starred_url":"https://api.github.com/users/jupe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jupe/subscriptions","organizations_url":"https://api.github.com/users/jupe/orgs","repos_url":"https://api.github.com/users/jupe/repos","events_url":"https://api.github.com/users/jupe/events{/privacy}","received_events_url":"https://api.github.com/users/jupe/received_events","type":"User","site_admin":false},"assignees":[{"login":"jupe","id":3822425,"avatar_url":"https://avatars.githubusercontent.com/u/3822425?v=3","gravatar_id":"","url":"https://api.github.com/users/jupe","html_url":"https://github.com/jupe","followers_url":"https://api.github.com/users/jupe/followers","following_url":"https://api.github.com/users/jupe/following{/other_user}","gists_url":"https://api.github.com/users/jupe/gists{/gist_id}","starred_url":"https://api.github.com/users/jupe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jupe/subscriptions","organizations_url":"https://api.github.com/users/jupe/orgs","repos_url":"https://api.github.com/users/jupe/repos","events_url":"https://api.github.com/users/jupe/events{/privacy}","received_events_url":"https://api.github.com/users/jupe/received_events","type":"User","site_admin":false},{"login":"lorjala","id":15421413,"avatar_url":"https://avatars.githubusercontent.com/u/15421413?v=3","gravatar_id":"","url":"https://api.github.com/users/lorjala","html_url":"https://github.com/lorjala","followers_url":"https://api.github.com/users/lorjala/followers","following_url":"https://api.github.com/users/lorjala/following{/other_user}","gists_url":"https://api.github.com/users/lorjala/gists{/gist_id}","starred_url":"https://api.github.com/users/lorjala/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lorjala/subscriptions","organizations_url":"https://api.github.com/users/lorjala/orgs","repos_url":"https://api.github.com/users/lorjala/repos","events_url":"https://api.github.com/users/lorjala/events{/privacy}","received_events_url":"https://api.github.com/users/lorjala/received_events","type":"User","site_admin":false},{"login":"olkorhon","id":15610244,"avatar_url":"https://avatars.githubusercontent.com/u/15610244?v=3","gravatar_id":"","url":"https://api.github.com/users/olkorhon","html_url":"https://github.com/olkorhon","followers_url":"https://api.github.com/users/olkorhon/followers","following_url":"https://api.github.com/users/olkorhon/following{/other_user}","gists_url":"https://api.github.com/users/olkorhon/gists{/gist_id}","starred_url":"https://api.github.com/users/olkorhon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/olkorhon/subscriptions","organizations_url":"https://api.github.com/users/olkorhon/orgs","repos_url":"https://api.github.com/users/olkorhon/repos","events_url":"https://api.github.com/users/olkorhon/events{/privacy}","received_events_url":"https://api.github.com/users/olkorhon/received_events","type":"User","site_admin":false},{"login":"paavoee","id":15650873,"avatar_url":"https://avatars.githubusercontent.com/u/15650873?v=3","gravatar_id":"","url":"https://api.github.com/users/paavoee","html_url":"https://github.com/paavoee","followers_url":"https://api.github.com/users/paavoee/followers","following_url":"https://api.github.com/users/paavoee/following{/other_user}","gists_url":"https://api.github.com/users/paavoee/gists{/gist_id}","starred_url":"https://api.github.com/users/paavoee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/paavoee/subscriptions","organizations_url":"https://api.github.com/users/paavoee/orgs","repos_url":"https://api.github.com/users/paavoee/repos","events_url":"https://api.github.com/users/paavoee/events{/privacy}","received_events_url":"https://api.github.com/users/paavoee/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/OpenTMI/opentmi/pulls/13/commits","review_comments_url":"https://api.github.com/repos/OpenTMI/opentmi/pulls/13/comments","review_comment_url":"https://api.github.com/repos/OpenTMI/opentmi/pulls/comments{/number}","comments_url":"https://api.github.com/repos/OpenTMI/opentmi/issues/13/comments","statuses_url":"https://api.github.com/repos/OpenTMI/opentmi/statuses/e6d8e669f315194c4deac71ed699c438bc3c2d6b","head":{"label":"OpenTMI:inventory","ref":"inventory","sha":"e6d8e669f315194c4deac71ed699c438bc3c2d6b","user":{"login":"OpenTMI","id":15953937,"avatar_url":"https://avatars.githubusercontent.com/u/15953937?v=3","gravatar_id":"","url":"https://api.github.com/users/OpenTMI","html_url":"https://github.com/OpenTMI","followers_url":"https://api.github.com/users/OpenTMI/followers","following_url":"https://api.github.com/users/OpenTMI/following{/other_user}","gists_url":"https://api.github.com/users/OpenTMI/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenTMI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenTMI/subscriptions","organizations_url":"https://api.github.com/users/OpenTMI/orgs","repos_url":"https://api.github.com/users/OpenTMI/repos","events_url":"https://api.github.com/users/OpenTMI/events{/privacy}","received_events_url":"https://api.github.com/users/OpenTMI/received_events","type":"Organization","site_admin":false},"repo":{"id":46608376,"name":"opentmi","full_name":"OpenTMI/opentmi","owner":{"login":"OpenTMI","id":15953937,"avatar_url":"https://avatars.githubusercontent.com/u/15953937?v=3","gravatar_id":"","url":"https://api.github.com/users/OpenTMI","html_url":"https://github.com/OpenTMI","followers_url":"https://api.github.com/users/OpenTMI/followers","following_url":"https://api.github.com/users/OpenTMI/following{/other_user}","gists_url":"https://api.github.com/users/OpenTMI/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenTMI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenTMI/subscriptions","organizations_url":"https://api.github.com/users/OpenTMI/orgs","repos_url":"https://api.github.com/users/OpenTMI/repos","events_url":"https://api.github.com/users/OpenTMI/events{/privacy}","received_events_url":"https://api.github.com/users/OpenTMI/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/OpenTMI/opentmi","description":"OpenTMI (Test Management Infrastructure) Core","fork":false,"url":"https://api.github.com/repos/OpenTMI/opentmi","forks_url":"https://api.github.com/repos/OpenTMI/opentmi/forks","keys_url":"https://api.github.com/repos/OpenTMI/opentmi/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OpenTMI/opentmi/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OpenTMI/opentmi/teams","hooks_url":"https://api.github.com/repos/OpenTMI/opentmi/hooks","issue_events_url":"https://api.github.com/repos/OpenTMI/opentmi/issues/events{/number}","events_url":"https://api.github.com/repos/OpenTMI/opentmi/events","assignees_url":"https://api.github.com/repos/OpenTMI/opentmi/assignees{/user}","branches_url":"https://api.github.com/repos/OpenTMI/opentmi/branches{/branch}","tags_url":"https://api.github.com/repos/OpenTMI/opentmi/tags","blobs_url":"https://api.github.com/repos/OpenTMI/opentmi/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OpenTMI/opentmi/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OpenTMI/opentmi/git/refs{/sha}","trees_url":"https://api.github.com/repos/OpenTMI/opentmi/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OpenTMI/opentmi/statuses/{sha}","languages_url":"https://api.github.com/repos/OpenTMI/opentmi/languages","stargazers_url":"https://api.github.com/repos/OpenTMI/opentmi/stargazers","contributors_url":"https://api.github.com/repos/OpenTMI/opentmi/contributors","subscribers_url":"https://api.github.com/repos/OpenTMI/opentmi/subscribers","subscription_url":"https://api.github.com/repos/OpenTMI/opentmi/subscription","commits_url":"https://api.github.com/repos/OpenTMI/opentmi/commits{/sha}","git_commits_url":"https://api.github.com/repos/OpenTMI/opentmi/git/commits{/sha}","comments_url":"https://api.github.com/repos/OpenTMI/opentmi/comments{/number}","issue_comment_url":"https://api.github.com/repos/OpenTMI/opentmi/issues/comments{/number}","contents_url":"https://api.github.com/repos/OpenTMI/opentmi/contents/{+path}","compare_url":"https://api.github.com/repos/OpenTMI/opentmi/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OpenTMI/opentmi/merges","archive_url":"https://api.github.com/repos/OpenTMI/opentmi/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OpenTMI/opentmi/downloads","issues_url":"https://api.github.com/repos/OpenTMI/opentmi/issues{/number}","pulls_url":"https://api.github.com/repos/OpenTMI/opentmi/pulls{/number}","milestones_url":"https://api.github.com/repos/OpenTMI/opentmi/milestones{/number}","notifications_url":"https://api.github.com/repos/OpenTMI/opentmi/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OpenTMI/opentmi/labels{/name}","releases_url":"https://api.github.com/repos/OpenTMI/opentmi/releases{/id}","deployments_url":"https://api.github.com/repos/OpenTMI/opentmi/deployments","created_at":"2015-11-21T09:02:46Z","updated_at":"2016-11-18T08:23:33Z","pushed_at":"2016-12-01T17:48:27Z","git_url":"git://github.com/OpenTMI/opentmi.git","ssh_url":"git@github.com:OpenTMI/opentmi.git","clone_url":"https://github.com/OpenTMI/opentmi.git","svn_url":"https://github.com/OpenTMI/opentmi","homepage":"","size":688,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":1,"forks":2,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"OpenTMI:master","ref":"master","sha":"c7959f45e4900012d69276209ae2cb092e16d95a","user":{"login":"OpenTMI","id":15953937,"avatar_url":"https://avatars.githubusercontent.com/u/15953937?v=3","gravatar_id":"","url":"https://api.github.com/users/OpenTMI","html_url":"https://github.com/OpenTMI","followers_url":"https://api.github.com/users/OpenTMI/followers","following_url":"https://api.github.com/users/OpenTMI/following{/other_user}","gists_url":"https://api.github.com/users/OpenTMI/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenTMI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenTMI/subscriptions","organizations_url":"https://api.github.com/users/OpenTMI/orgs","repos_url":"https://api.github.com/users/OpenTMI/repos","events_url":"https://api.github.com/users/OpenTMI/events{/privacy}","received_events_url":"https://api.github.com/users/OpenTMI/received_events","type":"Organization","site_admin":false},"repo":{"id":46608376,"name":"opentmi","full_name":"OpenTMI/opentmi","owner":{"login":"OpenTMI","id":15953937,"avatar_url":"https://avatars.githubusercontent.com/u/15953937?v=3","gravatar_id":"","url":"https://api.github.com/users/OpenTMI","html_url":"https://github.com/OpenTMI","followers_url":"https://api.github.com/users/OpenTMI/followers","following_url":"https://api.github.com/users/OpenTMI/following{/other_user}","gists_url":"https://api.github.com/users/OpenTMI/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenTMI/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenTMI/subscriptions","organizations_url":"https://api.github.com/users/OpenTMI/orgs","repos_url":"https://api.github.com/users/OpenTMI/repos","events_url":"https://api.github.com/users/OpenTMI/events{/privacy}","received_events_url":"https://api.github.com/users/OpenTMI/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/OpenTMI/opentmi","description":"OpenTMI (Test Management Infrastructure) Core","fork":false,"url":"https://api.github.com/repos/OpenTMI/opentmi","forks_url":"https://api.github.com/repos/OpenTMI/opentmi/forks","keys_url":"https://api.github.com/repos/OpenTMI/opentmi/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OpenTMI/opentmi/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OpenTMI/opentmi/teams","hooks_url":"https://api.github.com/repos/OpenTMI/opentmi/hooks","issue_events_url":"https://api.github.com/repos/OpenTMI/opentmi/issues/events{/number}","events_url":"https://api.github.com/repos/OpenTMI/opentmi/events","assignees_url":"https://api.github.com/repos/OpenTMI/opentmi/assignees{/user}","branches_url":"https://api.github.com/repos/OpenTMI/opentmi/branches{/branch}","tags_url":"https://api.github.com/repos/OpenTMI/opentmi/tags","blobs_url":"https://api.github.com/repos/OpenTMI/opentmi/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OpenTMI/opentmi/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OpenTMI/opentmi/git/refs{/sha}","trees_url":"https://api.github.com/repos/OpenTMI/opentmi/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OpenTMI/opentmi/statuses/{sha}","languages_url":"https://api.github.com/repos/OpenTMI/opentmi/languages","stargazers_url":"https://api.github.com/repos/OpenTMI/opentmi/stargazers","contributors_url":"https://api.github.com/repos/OpenTMI/opentmi/contributors","subscribers_url":"https://api.github.com/repos/OpenTMI/opentmi/subscribers","subscription_url":"https://api.github.com/repos/OpenTMI/opentmi/subscription","commits_url":"https://api.github.com/repos/OpenTMI/opentmi/commits{/sha}","git_commits_url":"https://api.github.com/repos/OpenTMI/opentmi/git/commits{/sha}","comments_url":"https://api.github.com/repos/OpenTMI/opentmi/comments{/number}","issue_comment_url":"https://api.github.com/repos/OpenTMI/opentmi/issues/comments{/number}","contents_url":"https://api.github.com/repos/OpenTMI/opentmi/contents/{+path}","compare_url":"https://api.github.com/repos/OpenTMI/opentmi/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OpenTMI/opentmi/merges","archive_url":"https://api.github.com/repos/OpenTMI/opentmi/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OpenTMI/opentmi/downloads","issues_url":"https://api.github.com/repos/OpenTMI/opentmi/issues{/number}","pulls_url":"https://api.github.com/repos/OpenTMI/opentmi/pulls{/number}","milestones_url":"https://api.github.com/repos/OpenTMI/opentmi/milestones{/number}","notifications_url":"https://api.github.com/repos/OpenTMI/opentmi/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OpenTMI/opentmi/labels{/name}","releases_url":"https://api.github.com/repos/OpenTMI/opentmi/releases{/id}","deployments_url":"https://api.github.com/repos/OpenTMI/opentmi/deployments","created_at":"2015-11-21T09:02:46Z","updated_at":"2016-11-18T08:23:33Z","pushed_at":"2016-12-01T17:48:27Z","git_url":"git://github.com/OpenTMI/opentmi.git","ssh_url":"git@github.com:OpenTMI/opentmi.git","clone_url":"https://github.com/OpenTMI/opentmi.git","svn_url":"https://github.com/OpenTMI/opentmi","homepage":"","size":688,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":1,"forks":2,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/OpenTMI/opentmi/pulls/13"},"html":{"href":"https://github.com/OpenTMI/opentmi/pull/13"},"issue":{"href":"https://api.github.com/repos/OpenTMI/opentmi/issues/13"},"comments":{"href":"https://api.github.com/repos/OpenTMI/opentmi/issues/13/comments"},"review_comments":{"href":"https://api.github.com/repos/OpenTMI/opentmi/pulls/13/comments"},"review_comment":{"href":"https://api.github.com/repos/OpenTMI/opentmi/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/OpenTMI/opentmi/pulls/13/commits"},"statuses":{"href":"https://api.github.com/repos/OpenTMI/opentmi/statuses/e6d8e669f315194c4deac71ed699c438bc3c2d6b"}}}}
{"actor":{"display_login":"jupe"}}