From 01c43548d7e05e5f7fb47bc65d358eede4489661 Mon Sep 17 00:00:00 2001 From: abe545 Date: Tue, 18 Mar 2014 23:07:57 -0400 Subject: [PATCH] Fixed authentication bug when token timed out. Added missing id property to the repo object. Enabled adding/remove repos by essentially creating pass-through methods for setupRepo and teardownRepo --- lib/codeplex.js | 33 ++++++++++++++++++++++++++++----- package.json | 3 ++- webapp.js | 22 +++++++++++++++------- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/lib/codeplex.js b/lib/codeplex.js index d687ee5..0d5ab71 100644 --- a/lib/codeplex.js +++ b/lib/codeplex.js @@ -1,12 +1,16 @@ -var https = require('https'); +var https = require('https') + , TokenProvider = require('refresh-token'); module.exports = { - getRepos: function(account, callback) { - getCodeplex(account, '/api/user/projects', callback); + getRepos: function(account, appConfig, callback) { + getCodeplex(account, appConfig, '/api/user/projects', callback); + }, + getAvailableHooks: function(account, appConfig, projectName, callback) { + getCodeplex(account, appConfig, '/api/projects/' + projectName + '/hooks', callback); } } -function getCodeplex(account, resourcePath, callback) { +function getCodeplex(account, appConfig, resourcePath, callback) { var options = { hostname: 'www.codeplex.com', @@ -31,7 +35,26 @@ function getCodeplex(account, resourcePath, callback) { var fin = JSON.parse(json); // this is an error message - if (fin.Message) { callback(fin.Message, null); } + if (fin.Message) { + if (appConfig.clientId && appConfig.clientSecret && fin.Message === 'Authentication required.') { + var tokenProvider = new TokenProvider('https://www.codeplex.com/oauth/token', { + refresh_token: account.refreshToken, + client_id: appConfig.clientId, + client_secret: appConfig.clientSecret + }); + + tokenProvider.getToken(function (err, token) { + if (err) { callback(err, null); } + else { + account.accessToken = token; + getCodeplex(account, resourcePath, callback); + } + }); + } + else { + callback(fin.Message, null); + } + } else { callback(null, fin); } }); }); diff --git a/package.json b/package.json index 7b3fea4..cdc02ea 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "license": "GPL-2.0", "readmeFilename": "Readme.md", "dependencies": { - "passport-oauth2": "1.x.x" + "passport-oauth2": "1.x.x", + "refresh-token": "0.0.2" }, "bugs": { "url": "https://github.com/abe545/codeplex-for-strider/issues" diff --git a/webapp.js b/webapp.js index cfca4bb..2b6fb1f 100644 --- a/webapp.js +++ b/webapp.js @@ -10,6 +10,7 @@ module.exports = { accountConfig: { accessToken: String, + refreshToken: String, name: String, avatar: String }, @@ -17,7 +18,7 @@ module.exports = { config: { sourceType: String, sourceUrl: String, - role: String + repoName: String }, // oauth global routes @@ -41,12 +42,13 @@ module.exports = { clientID: this.appConfig.clientId, clientSecret: this.appConfig.clientSecret, callbackURL: this.appConfig.hostname + '/ext/codeplex/oauth/callback', + scope: 'project_info', passReqToCallback: true }, validateAuth)); }, listRepos: function (account, callback) { - codeplex.getRepos(account, function(err, data) { + codeplex.getRepos(account, this.appConfig, function(err, data) { if (err) return callback(err) callback(null, data.map(function(repo) { return parseRepo(account, repo); })) }); @@ -55,9 +57,13 @@ module.exports = { isSetup: function (account) {}, setupRepo: function (account, config, project, done) { + if (!account.accessToken) return done(new Error('Codeplex account not configured')); + done(null, config); }, teardownRepo: function (account, config, project, done) { + if (!account.accessToken) return done(new Error('Codeplex account not configured')); + done(null, config); }, getBranches: function (account, config, project, done) { @@ -67,7 +73,7 @@ module.exports = { } } -function validateAuth(req, accessToken, parms, profile, done) { +function validateAuth(req, accessToken, refreshToken, parms, profile, done) { if (!req.user) { console.warn('Codeplex OAuth but no logged-in user') req.flash('account', "Cannot link a codeplex account if you aren't logged in") @@ -80,13 +86,13 @@ function validateAuth(req, accessToken, parms, profile, done) { return done(null, req.user) } - req.user.accounts.push(makeAccount(accessToken, profile)) + req.user.accounts.push(makeAccount(accessToken, refreshToken, profile)) req.user.save(function (err) { done(err, req.user); }) } -function makeAccount(accessToken, profile) { +function makeAccount(accessToken, refreshToken, profile) { var username = profile.UserName; return { provider: 'codeplex', @@ -95,6 +101,7 @@ function makeAccount(accessToken, profile) { title: username, config: { accessToken: accessToken, + refreshToken: refreshToken, name: username, avatar: profile.Avatar } @@ -103,15 +110,16 @@ function makeAccount(accessToken, profile) { function parseRepo(account, repo) { return { + id: account.name + '/' + repo.Name, name: account.name + '/' + repo.Name, display_name: repo.Title, display_url: repo.Url, - group: account.name, + group: repo.Role, 'private': !repo.IsPublished, config: { sourceType: repo.SourceControl.ServerType, sourceUrl: repo.SourceControl.Url, - role: repo.Role + repoName: repo.Name } } } \ No newline at end of file