mirror of
https://github.com/moparisthebest/mail
synced 2024-11-26 02:42:17 -05:00
Remove cached OAuth token before reconnect
This commit is contained in:
parent
eb0002c8d5
commit
c4337fba30
@ -13,7 +13,7 @@
|
||||
"crypto-lib": "~0.2.1",
|
||||
"imap-client": "~0.3.7",
|
||||
"mailreader": "~0.3.5",
|
||||
"pgpmailer": "~0.3.10",
|
||||
"pgpmailer": "~0.3.11",
|
||||
"pgpbuilder": "~0.3.7",
|
||||
"requirejs": "2.1.14",
|
||||
"axe-logger": "~0.0.2",
|
||||
|
@ -133,7 +133,8 @@ define(function(require) {
|
||||
function initClients(credentials) {
|
||||
var pgpMailer = new PgpMailer(credentials.smtp, self._pgpbuilder);
|
||||
var imapClient = new ImapClient(credentials.imap);
|
||||
imapClient.onError = onImapError;
|
||||
imapClient.onError = onConnectionError;
|
||||
pgpMailer.onError = onConnectionError;
|
||||
|
||||
// certificate update handling
|
||||
imapClient.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'imap', self.onConnect, self.onError);
|
||||
@ -151,19 +152,19 @@ define(function(require) {
|
||||
}, callback);
|
||||
}
|
||||
|
||||
function onImapError(error) {
|
||||
axe.debug('IMAP connection error. Attempting reconnect in ' + config.reconnectInterval + ' ms. Error: ' + (error.errMsg || error.message) + (error.stack ? ('\n' + error.stack) : ''));
|
||||
function onConnectionError(error) {
|
||||
axe.debug('Connection error. Attempting reconnect in ' + config.reconnectInterval + ' ms. Error: ' + (error.errMsg || error.message) + (error.stack ? ('\n' + error.stack) : ''));
|
||||
|
||||
setTimeout(function() {
|
||||
axe.debug('IMAP reconnecting...');
|
||||
axe.debug('Reconnecting...');
|
||||
// re-init client modules on error
|
||||
self.onConnect(function(err) {
|
||||
if (err) {
|
||||
axe.error('IMAP reconnect attempt failed! ' + (err.errMsg || err.message) + (err.stack ? ('\n' + err.stack) : ''));
|
||||
axe.error('Reconnect attempt failed! ' + (err.errMsg || err.message) + (err.stack ? ('\n' + err.stack) : ''));
|
||||
return;
|
||||
}
|
||||
|
||||
axe.debug('IMAP reconnect attempt complete.');
|
||||
axe.debug('Reconnect attempt complete.');
|
||||
});
|
||||
}, config.reconnectInterval);
|
||||
}
|
||||
|
@ -256,8 +256,18 @@ define(function(require) {
|
||||
Auth.prototype.getOAuthToken = function(callback) {
|
||||
var self = this;
|
||||
|
||||
// get a fresh oauth token
|
||||
self._oauth.getOAuthToken(self.emailAddress, function(err, oauthToken) {
|
||||
if (self.oauthToken) {
|
||||
// removed cached token and get a new one
|
||||
self._oauth.refreshToken({
|
||||
emailAddress: self.emailAddress,
|
||||
oldToken: self.oauthToken
|
||||
}, onToken);
|
||||
} else {
|
||||
// get a fresh oauth token
|
||||
self._oauth.getOAuthToken(self.emailAddress, onToken);
|
||||
}
|
||||
|
||||
function onToken(err, oauthToken) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
@ -278,7 +288,7 @@ define(function(require) {
|
||||
self.emailAddress = emailAddress;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -5,12 +5,17 @@ define(function() {
|
||||
this._googleApi = googleApi;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if chrome.identity api is supported
|
||||
* @return {Boolean} If is supported
|
||||
*/
|
||||
OAuth.prototype.isSupported = function() {
|
||||
return !!(window.chrome && chrome.identity);
|
||||
};
|
||||
|
||||
/**
|
||||
* Request an OAuth token from chrome for gmail users
|
||||
* @param {String} emailAddress The user's email address (optional)
|
||||
*/
|
||||
OAuth.prototype.getOAuthToken = function(emailAddress, callback) {
|
||||
var idOptions = {
|
||||
@ -19,7 +24,7 @@ define(function() {
|
||||
|
||||
// check which runtime the app is running under
|
||||
chrome.runtime.getPlatformInfo(function(platformInfo) {
|
||||
if ((chrome && chrome.runtime && chrome.runtime.lastError) || !platformInfo) {
|
||||
if (chrome.runtime.lastError || !platformInfo) {
|
||||
callback(new Error('Error getting chrome platform info!'));
|
||||
return;
|
||||
}
|
||||
@ -31,7 +36,7 @@ define(function() {
|
||||
|
||||
// get OAuth Token from chrome
|
||||
chrome.identity.getAuthToken(idOptions, function(token) {
|
||||
if ((chrome && chrome.runtime && chrome.runtime.lastError) || !token) {
|
||||
if (chrome.runtime.lastError || !token) {
|
||||
callback({
|
||||
errMsg: 'Error fetching an OAuth token for the user!'
|
||||
});
|
||||
@ -43,6 +48,32 @@ define(function() {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an old OAuth token and get a new one.
|
||||
* @param {String} options.oldToken The old token to be removed
|
||||
* @param {String} options.emailAddress The user's email address (optional)
|
||||
*/
|
||||
OAuth.prototype.refreshToken = function(options, callback) {
|
||||
var self = this;
|
||||
|
||||
if (!options.oldToken) {
|
||||
callback(new Error('oldToken option not set!'));
|
||||
return;
|
||||
}
|
||||
|
||||
// remove cached token
|
||||
chrome.identity.removeCachedAuthToken({
|
||||
token: options.oldToken
|
||||
}, function() {
|
||||
// get a new token
|
||||
self.getOAuthToken(options.emailAddress, callback);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get email address from google api
|
||||
* @param {String} token The oauth token
|
||||
*/
|
||||
OAuth.prototype.queryEmailAddress = function(token, callback) {
|
||||
if (!token) {
|
||||
callback({
|
||||
|
@ -146,6 +146,26 @@ define(function(require) {
|
||||
});
|
||||
|
||||
describe('#getOAuthToken', function() {
|
||||
it('should refresh token with known email address', function(done) {
|
||||
auth.emailAddress = emailAddress;
|
||||
auth.oauthToken = 'oldToken';
|
||||
|
||||
oauthStub.refreshToken.withArgs({
|
||||
emailAddress: emailAddress,
|
||||
oldToken: 'oldToken'
|
||||
}).yieldsAsync(null, oauthToken);
|
||||
|
||||
auth.getOAuthToken(function(err) {
|
||||
expect(err).to.not.exist;
|
||||
expect(auth.emailAddress).to.equal(emailAddress);
|
||||
expect(auth.oauthToken).to.equal(oauthToken);
|
||||
|
||||
expect(oauthStub.refreshToken.calledOnce).to.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch token with known email address', function(done) {
|
||||
auth.emailAddress = emailAddress;
|
||||
oauthStub.getOAuthToken.withArgs(emailAddress).yieldsAsync(null, oauthToken);
|
||||
|
@ -6,7 +6,7 @@ define(function(require) {
|
||||
expect = chai.expect;
|
||||
|
||||
describe('OAuth unit tests', function() {
|
||||
var oauth, googleApiStub, identityStub, getPlatformInfoStub,
|
||||
var oauth, googleApiStub, identityStub, getPlatformInfoStub, removeCachedStub,
|
||||
testEmail = 'test@example.com';
|
||||
|
||||
beforeEach(function() {
|
||||
@ -21,6 +21,11 @@ define(function(require) {
|
||||
}
|
||||
identityStub = sinon.stub(window.chrome.identity, 'getAuthToken');
|
||||
|
||||
if (typeof window.chrome.identity.removeCachedAuthToken !== 'function') {
|
||||
window.chrome.identity.removeCachedAuthToken = function() {};
|
||||
}
|
||||
removeCachedStub = sinon.stub(window.chrome.identity, 'removeCachedAuthToken');
|
||||
|
||||
window.chrome.runtime = window.chrome.runtime || {};
|
||||
if (typeof window.chrome.runtime.getPlatformInfo !== 'function') {
|
||||
window.chrome.runtime.getPlatformInfo = function() {};
|
||||
@ -31,6 +36,7 @@ define(function(require) {
|
||||
afterEach(function() {
|
||||
identityStub.restore();
|
||||
getPlatformInfoStub.restore();
|
||||
removeCachedStub.restore();
|
||||
});
|
||||
|
||||
describe('isSupported', function() {
|
||||
@ -39,6 +45,61 @@ define(function(require) {
|
||||
});
|
||||
});
|
||||
|
||||
describe('refreshToken', function() {
|
||||
var getOAuthTokenStub;
|
||||
|
||||
beforeEach(function() {
|
||||
getOAuthTokenStub = sinon.stub(oauth, 'getOAuthToken');
|
||||
});
|
||||
afterEach(function() {
|
||||
getOAuthTokenStub.restore();
|
||||
});
|
||||
|
||||
it('should work', function() {
|
||||
removeCachedStub.withArgs({
|
||||
token: 'oldToken'
|
||||
}).yields();
|
||||
|
||||
getOAuthTokenStub.withArgs(testEmail).yields();
|
||||
|
||||
oauth.refreshToken({
|
||||
oldToken: 'oldToken',
|
||||
emailAddress: testEmail
|
||||
}, function(err) {
|
||||
expect(err).to.not.exist;
|
||||
expect(removeCachedStub.calledOnce).to.be.true;
|
||||
expect(getOAuthTokenStub.calledOnce).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it('should work without email', function() {
|
||||
removeCachedStub.withArgs({
|
||||
token: 'oldToken'
|
||||
}).yields();
|
||||
|
||||
getOAuthTokenStub.withArgs(undefined).yields();
|
||||
|
||||
oauth.refreshToken({
|
||||
oldToken: 'oldToken',
|
||||
}, function(err) {
|
||||
expect(err).to.not.exist;
|
||||
expect(removeCachedStub.calledOnce).to.be.true;
|
||||
expect(getOAuthTokenStub.calledOnce).to.be.true;
|
||||
expect(getOAuthTokenStub.calledWith(undefined)).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail without all options', function() {
|
||||
oauth.refreshToken({
|
||||
emailAddress: testEmail
|
||||
}, function(err) {
|
||||
expect(err).to.exist;
|
||||
expect(removeCachedStub.called).to.be.false;
|
||||
expect(getOAuthTokenStub.called).to.be.false;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getOAuthToken', function() {
|
||||
it('should work for empty emailAddress', function(done) {
|
||||
getPlatformInfoStub.yields({
|
||||
|
Loading…
Reference in New Issue
Block a user