From fe279e4a754efe4a9d5cbef7145d4e5da5296a42 Mon Sep 17 00:00:00 2001 From: Thaddee Tyl Date: Wed, 22 Jun 2016 10:12:07 +0200 Subject: [PATCH] GitHub auth: removal of unauthorized user tokens --- lib/github-auth.js | 49 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/lib/github-auth.js b/lib/github-auth.js index b360e2a..52b02f5 100644 --- a/lib/github-auth.js +++ b/lib/github-auth.js @@ -118,16 +118,31 @@ function sendTokenToAllServers(token) { var reqRemaining = new Map(); var lowestReqRemaining = Infinity, lowestReqRemainingToken; -// token: client token as a string. -// reqs: number of requests remaining. -function setReqRemaining(token, reqs) { +// Set lowestReqRemaining* variables if the token / requests remaining +// combination passed as a parameter is lower than previously registered. +function setLowestReqRemaining(token, reqs) { if (reqs <= lowestReqRemaining) { lowestReqRemaining = reqs; lowestReqRemainingToken = token; } +} + +// token: client token as a string. +// reqs: number of requests remaining. +function setReqRemaining(token, reqs) { + setLowestReqRemaining(token, reqs); reqRemaining.set(token, reqs); } +function rmReqRemaining(token) { + reqRemaining.delete(token); + if (lowestReqRemainingToken === token) { + lowestReqRemaining = Infinity; + lowestReqRemainingToken = undefined; + reqRemaining.forEach(setLowestReqRemaining); + } +} + function addGithubToken(token) { setReqRemaining(token, Infinity); // Insert it only if it is not registered yet. @@ -136,6 +151,15 @@ function addGithubToken(token) { } } +function rmGithubToken(token) { + rmReqRemaining(token); + // Remove it only if it is in there. + var idx = githubUserTokens.data.indexOf(token); + if (idx >= 0) { + githubUserTokens.data.splice(idx, 1); + } +} + // Personal tokens allow access to GitHub private repositories. // You can manage your personal GitHub token at // . @@ -143,7 +167,8 @@ if (serverSecrets && serverSecrets.gh_token) { addGithubToken(serverSecrets.gh_token); } -// Modify headers, return a URL (or an object to be used by request()). +// Act like request(), but tweak headers and query to avoid hitting a rate +// limit. function githubRequest(request, url, query, cb) { query = query || {}; // A special User-Agent is required: @@ -152,11 +177,11 @@ function githubRequest(request, url, query, cb) { 'User-Agent': 'Shields.io', 'Accept': 'application/vnd.github.v3+json', }; - var token; + var githubToken; if (lowestReqRemainingToken != null && lowestReqRemaining > 0) { - token = lowestReqRemainingToken; - headers['Authorization'] = 'token ' + token; + githubToken = lowestReqRemainingToken; + headers['Authorization'] = 'token ' + githubToken; } else if (serverSecrets && serverSecrets.gh_client_id) { // Using our OAuth App secret grants us 5000 req/hour // instead of the standard 60 req/hour. @@ -167,9 +192,13 @@ function githubRequest(request, url, query, cb) { var qs = querystring.stringify(query); if (qs) { url += '?' + qs; } request(url, {headers: headers}, function(err, res, buffer) { - if (token != null) { - var remaining = +res.headers['x-ratelimit-remaining']; - setReqRemaining(token, remaining); + if (githubToken != null) { + if (res.statusCode === 401) { // Unauthorized. + rmGithubToken(githubToken); + } else { + var remaining = +res.headers['x-ratelimit-remaining']; + setReqRemaining(githubToken, remaining); + } } cb(err, res, buffer); });