Refactor auth

This commit is contained in:
Tankred Hase 2014-12-11 20:27:55 +01:00
parent 15b902acf6
commit 26553e49d7
3 changed files with 193 additions and 274 deletions

View File

@ -170,8 +170,8 @@ Account.prototype.onConnect = function(callback) {
pgpMailer.onError = onConnectionError;
// certificate update handling
imapClient.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'imap', self.onConnect.bind(self), self._dialog.error);
pgpMailer.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'smtp', self.onConnect.bind(self), self._dialog.error);
imapClient.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'imap', self.onConnect.bind(self)).catch(self._dialog.error);
pgpMailer.onCert = self._auth.handleCertificateUpdate.bind(self._auth, 'smtp', self.onConnect.bind(self)).catch(self._dialog.error);
// connect to clients
self._emailDao.onConnect({

View File

@ -26,22 +26,21 @@ var SMTP_DB_KEY = 'smtp';
* auth.getCredentials(...); // called to gather all the information to connect to IMAP/SMTP,
* username, password / oauth token, IMAP/SMTP server host names, ...
*/
function Auth($q, appConfigStore, oauth, pgp) {
this._q = $q;
function Auth(appConfigStore, oauth, pgp) {
this._appConfigStore = appConfigStore;
this._oauth = oauth;
this._pgp = pgp;
this._initialized = false;
}
/**
* Initialize the service
*/
Auth.prototype.init = function(callback) {
Auth.prototype.init = function() {
var self = this;
self._appConfigStore.init(APP_CONFIG_DB_NAME, function(error) {
self._initialized = !error;
callback(error);
return self._appConfigStore.init(APP_CONFIG_DB_NAME).then(function() {
self._initialized = true;
});
};
@ -58,84 +57,62 @@ Auth.prototype.isInitialized = function() {
* 2 a) ... in an oauth setting, retrieves a fresh oauth token from the Chrome Identity API.
* 2 b) ... in a user/passwd setting, does not need to do additional work.
* 3) Loads the intermediate certs from the configuration.
*
* @param {Function} callback(err, credentials)
*/
Auth.prototype.getCredentials = function(callback) {
Auth.prototype.getCredentials = function() {
var self = this;
if (!self.emailAddress) {
// we're not yet initialized, so let's load our stuff from disk
self._loadCredentials(function(err) {
if (err) {
return callback(err);
}
chooseLogin();
});
return;
return self._loadCredentials().then(chooseLogin);
}
chooseLogin();
return chooseLogin();
function chooseLogin() {
if (self.useOAuth(self.imap.host) && !self.password) {
// oauth login
self.getOAuthToken(function(err) {
if (err) {
return callback(err);
}
done();
});
return;
return self.getOAuthToken().then(done);
}
if (self.passwordNeedsDecryption) {
// decrypt password
self._pgp.decrypt(self.password, undefined, function(err, cleartext) {
if (err) {
return callback(err);
}
return self._pgp.decrypt(self.password, undefined).then(function(cleartext) {
self.passwordNeedsDecryption = false;
self.password = cleartext;
done();
});
return;
}).then(done);
}
done();
return done();
}
function done() {
var credentials = {
imap: {
secure: self.imap.secure,
port: self.imap.port,
host: self.imap.host,
ca: self.imap.ca,
auth: {
user: self.username,
xoauth2: self.oauthToken, // password or oauthToken is undefined
pass: self.password
return new Promise(function(resolve) {
var credentials = {
imap: {
secure: self.imap.secure,
port: self.imap.port,
host: self.imap.host,
ca: self.imap.ca,
auth: {
user: self.username,
xoauth2: self.oauthToken, // password or oauthToken is undefined
pass: self.password
}
},
smtp: {
secure: self.smtp.secure,
port: self.smtp.port,
host: self.smtp.host,
ca: self.smtp.ca,
auth: {
user: self.username,
xoauth2: self.oauthToken,
pass: self.password // password or oauthToken is undefined
}
}
},
smtp: {
secure: self.smtp.secure,
port: self.smtp.port,
host: self.smtp.host,
ca: self.smtp.ca,
auth: {
user: self.username,
xoauth2: self.oauthToken,
pass: self.password // password or oauthToken is undefined
}
}
};
callback(null, credentials);
};
resolve(credentials);
});
}
};
@ -161,35 +138,43 @@ Auth.prototype.setCredentials = function(options) {
Auth.prototype.storeCredentials = function() {
var self = this;
return self._q(function(resolve) {
if (!self.credentialsDirty) {
if (!self.credentialsDirty) {
// nothing to store if credentials not dirty
return new Promise(function(resolve) {
resolve();
});
}
// persist the config
var storeSmtp = self._appConfigStore.storeList([self.smtp], SMTP_DB_KEY);
var storeImap = self._appConfigStore.storeList([self.imap], IMAP_DB_KEY);
var storeEmailAddress = self._appConfigStore.storeList([self.emailAddress], EMAIL_ADDR_DB_KEY);
var storeUsername = self._appConfigStore.storeList([self.username], USERNAME_DB_KEY);
var storeRealname = self._appConfigStore.storeList([self.realname], REALNAME_DB_KEY);
var storePassword = new Promise(function(resolve) {
if (!self.password) {
resolve();
return;
}
// persist the config
var storeSmtp = self._appConfigStore.storeList([self.smtp], SMTP_DB_KEY);
var storeImap = self._appConfigStore.storeList([self.imap], IMAP_DB_KEY);
var storeEmailAddress = self._appConfigStore.storeList([self.emailAddress], EMAIL_ADDR_DB_KEY);
var storeUsername = self._appConfigStore.storeList([self.username], USERNAME_DB_KEY);
var storeRealname = self._appConfigStore.storeList([self.realname], REALNAME_DB_KEY);
var storePassword = self._q(function(resolve) {
if (!self.password) {
resolve();
return;
}
if (self.passwordNeedsDecryption) {
// password is not decrypted yet, so no need to re-encrypt it before storing...
return self._appConfigStore.storeList([self.password], PASSWD_DB_KEY).then(resolve);
}
return self._pgp.encrypt(self.password, undefined).then(function(ciphertext) {
return self._appConfigStore.storeList([ciphertext], PASSWD_DB_KEY).then(resolve);
});
if (self.passwordNeedsDecryption) {
// password is not decrypted yet, so no need to re-encrypt it before storing...
return self._appConfigStore.storeList([self.password], PASSWD_DB_KEY).then(resolve);
}
return self._pgp.encrypt(self.password, undefined).then(function(ciphertext) {
return self._appConfigStore.storeList([ciphertext], PASSWD_DB_KEY).then(resolve);
});
});
Promise.all([storeSmtp, storeImap, storeEmailAddress, storeUsername, storeRealname, storePassword]).then(resolve);
}).then(function() {
return Promise.all([
storeSmtp,
storeImap,
storeEmailAddress,
storeUsername,
storeRealname,
storePassword
]).then(function() {
self.credentialsDirty = false;
});
};
@ -197,25 +182,23 @@ Auth.prototype.storeCredentials = function() {
/**
* Returns the email address. Loads it from disk, if necessary
*/
Auth.prototype.getEmailAddress = function(callback) {
Auth.prototype.getEmailAddress = function() {
var self = this;
if (self.emailAddress) {
return callback(null, {
emailAddress: self.emailAddress,
realname: self.realname
return new Promise(function(resolve) {
resolve({
emailAddress: self.emailAddress,
realname: self.realname
});
});
}
self._loadCredentials(function(err) {
if (err) {
return callback(err);
}
callback(null, {
return self._loadCredentials().then(function() {
return {
emailAddress: self.emailAddress,
realname: self.realname
});
};
});
};
@ -250,40 +233,31 @@ Auth.prototype.useOAuth = function(hostname) {
* is android only, since the desktop chrome will query the user that is logged into chrome
* 3) fetch the email address for the oauth token from the chrome identity api
*/
Auth.prototype.getOAuthToken = function(callback) {
Auth.prototype.getOAuthToken = function() {
var self = this;
if (self.oauthToken) {
// removed cached token and get a new one
self._oauth.refreshToken({
return self._oauth.refreshToken({
emailAddress: self.emailAddress,
oldToken: self.oauthToken
}, onToken);
}).then(onToken);
} else {
// get a fresh oauth token
self._oauth.getOAuthToken(self.emailAddress, onToken);
return self._oauth.getOAuthToken(self.emailAddress).then(onToken);
}
function onToken(err, oauthToken) {
if (err) {
return callback(err);
}
function onToken(oauthToken) {
// shortcut if the email address is already known
if (self.emailAddress) {
self.oauthToken = oauthToken;
return callback();
return;
}
// query the email address
self._oauth.queryEmailAddress(oauthToken, function(err, emailAddress) {
if (err) {
return callback(err);
}
return self._oauth.queryEmailAddress(oauthToken).then(function(emailAddress) {
self.oauthToken = oauthToken;
self.emailAddress = emailAddress;
callback();
});
}
};
@ -291,67 +265,44 @@ Auth.prototype.getOAuthToken = function(callback) {
/**
* Loads email address, password, ... from disk and sets them on `this`
*/
Auth.prototype._loadCredentials = function(callback) {
Auth.prototype._loadCredentials = function() {
var self = this;
if (self.initialized) {
callback();
return new Promise(function(resolve) {
resolve();
});
}
loadFromDB(SMTP_DB_KEY, function(err, smtp) {
if (err) {
return callback(err);
}
return loadFromDB(SMTP_DB_KEY).then(function(smtp) {
self.smtp = smtp;
return loadFromDB(IMAP_DB_KEY);
}).then(function(imap) {
self.imap = imap;
return loadFromDB(USERNAME_DB_KEY);
loadFromDB(IMAP_DB_KEY, function(err, imap) {
if (err) {
return callback(err);
}
}).then(function(username) {
self.username = username;
return loadFromDB(REALNAME_DB_KEY);
}).then(function(realname) {
self.realname = realname;
return loadFromDB(EMAIL_ADDR_DB_KEY);
loadFromDB(USERNAME_DB_KEY, function(err, username) {
if (err) {
return callback(err);
}
}).then(function(emailAddress) {
self.emailAddress = emailAddress;
return loadFromDB(PASSWD_DB_KEY);
loadFromDB(REALNAME_DB_KEY, function(err, realname) {
if (err) {
return callback(err);
}
loadFromDB(EMAIL_ADDR_DB_KEY, function(err, emailAddress) {
if (err) {
return callback(err);
}
loadFromDB(PASSWD_DB_KEY, function(err, password) {
if (err) {
return callback(err);
}
self.emailAddress = emailAddress;
self.password = password;
self.passwordNeedsDecryption = !!password;
self.username = username;
self.realname = realname;
self.smtp = smtp;
self.imap = imap;
self.initialized = true;
callback();
});
});
});
});
});
}).then(function(password) {
self.password = password;
self.passwordNeedsDecryption = !!password;
self.initialized = true;
});
function loadFromDB(key, callback) {
self._appConfigStore.listItems(key, 0, null, function(err, cachedItems) {
callback(err, (!err && cachedItems && cachedItems[0]));
function loadFromDB(key) {
return self._appConfigStore.listItems(key, 0, null).then(function(cachedItems) {
return cachedItems && cachedItems[0];
});
}
};
@ -359,10 +310,9 @@ Auth.prototype._loadCredentials = function(callback) {
/**
* Handles certificate updates and errors by notifying the user.
* @param {String} component Either imap or smtp
* @param {Function} callback The error handler
* @param {[type]} pemEncodedCert The PEM encoded SSL certificate
*/
Auth.prototype.handleCertificateUpdate = function(component, onConnect, callback, pemEncodedCert) {
Auth.prototype.handleCertificateUpdate = function(component, onConnect, pemEncodedCert) {
var self = this;
axe.debug('new ssl certificate received: ' + pemEncodedCert);
@ -371,8 +321,7 @@ Auth.prototype.handleCertificateUpdate = function(component, onConnect, callback
// no previous ssl cert, trust on first use
self[component].ca = pemEncodedCert;
self.credentialsDirty = true;
self.storeCredentials(callback);
return;
return self.storeCredentials();
}
if (self[component].ca === pemEncodedCert) {
@ -381,51 +330,41 @@ Auth.prototype.handleCertificateUpdate = function(component, onConnect, callback
}
// previous ssl cert known, does not match: query user and certificate
callback({
title: str.updateCertificateTitle,
message: str.updateCertificateMessage.replace('{0}', self[component].host),
positiveBtnStr: str.updateCertificatePosBtn,
negativeBtnStr: str.updateCertificateNegBtn,
showNegativeBtn: true,
faqLink: str.certificateFaqLink,
callback: function(granted) {
if (!granted) {
return;
}
self[component].ca = pemEncodedCert;
self.credentialsDirty = true;
self.storeCredentials(function(err) {
if (err) {
callback(err);
return new Promise(function() {
throw {
title: str.updateCertificateTitle,
message: str.updateCertificateMessage.replace('{0}', self[component].host),
positiveBtnStr: str.updateCertificatePosBtn,
negativeBtnStr: str.updateCertificateNegBtn,
showNegativeBtn: true,
faqLink: str.certificateFaqLink,
callback: function(granted) {
if (!granted) {
return;
}
onConnect(callback);
});
}
self[component].ca = pemEncodedCert;
self.credentialsDirty = true;
return self.storeCredentials().then(function() {
return onConnect();
});
}
};
});
};
/**
* Logout of the app by clearing the app config store and in memory credentials
*/
Auth.prototype.logout = function(callback) {
Auth.prototype.logout = function() {
var self = this;
// clear app config db
self._appConfigStore.clear(function(err) {
if (err) {
callback(err);
return;
}
return self._appConfigStore.clear().then(function() {
// clear in memory cache
self.setCredentials({});
self.initialized = undefined;
self.credentialsDirty = undefined;
self.passwordNeedsDecryption = undefined;
callback();
});
};

View File

@ -50,16 +50,15 @@ describe('Auth unit tests', function() {
describe('#init', function() {
it('should initialize a user db', function(done) {
storageStub.init.withArgs(APP_CONFIG_DB_NAME).yields();
auth.init(function(err) {
expect(err).to.not.exist;
storageStub.init.withArgs(APP_CONFIG_DB_NAME).returns(resolves());
auth.init().then(function() {
expect(auth._initialized).to.be.true;
done();
});
});
it('should initialize a user db', function(done) {
storageStub.init.withArgs(APP_CONFIG_DB_NAME).yields(new Error());
auth.init(function(err) {
storageStub.init.withArgs(APP_CONFIG_DB_NAME).returns(rejects(new Error()));
auth.init().catch(function(err) {
expect(err).to.exist;
expect(auth._initialized).to.be.false;
done();
@ -69,17 +68,15 @@ describe('Auth unit tests', function() {
describe('#getCredentials', function() {
it('should load credentials and retrieve credentials from cfg', function(done) {
storageStub.listItems.withArgs(EMAIL_ADDR_DB_KEY, 0, null).yieldsAsync(null, [emailAddress]);
storageStub.listItems.withArgs(PASSWD_DB_KEY, 0, null).yieldsAsync(null, [encryptedPassword]);
storageStub.listItems.withArgs(USERNAME_DB_KEY, 0, null).yieldsAsync(null, [username]);
storageStub.listItems.withArgs(REALNAME_DB_KEY, 0, null).yieldsAsync(null, [realname]);
storageStub.listItems.withArgs(IMAP_DB_KEY, 0, null).yieldsAsync(null, [imap]);
storageStub.listItems.withArgs(SMTP_DB_KEY, 0, null).yieldsAsync(null, [smtp]);
pgpStub.decrypt.withArgs(encryptedPassword, undefined).yields(null, password);
auth.getCredentials(function(err, cred) {
expect(err).to.not.exist;
storageStub.listItems.withArgs(EMAIL_ADDR_DB_KEY, 0, null).returns(resolves([emailAddress]));
storageStub.listItems.withArgs(PASSWD_DB_KEY, 0, null).returns(resolves([encryptedPassword]));
storageStub.listItems.withArgs(USERNAME_DB_KEY, 0, null).returns(resolves([username]));
storageStub.listItems.withArgs(REALNAME_DB_KEY, 0, null).returns(resolves([realname]));
storageStub.listItems.withArgs(IMAP_DB_KEY, 0, null).returns(resolves([imap]));
storageStub.listItems.withArgs(SMTP_DB_KEY, 0, null).returns(resolves([smtp]));
pgpStub.decrypt.withArgs(encryptedPassword, undefined).returns(resolves(password));
auth.getCredentials().then(function(cred) {
expect(auth.emailAddress).to.equal(emailAddress);
expect(auth.password).to.equal(password);
@ -136,17 +133,15 @@ describe('Auth unit tests', function() {
auth.smtp = smtp;
auth.imap = imap;
storageStub.storeList.withArgs([encryptedPassword], PASSWD_DB_KEY).yieldsAsync();
storageStub.storeList.withArgs([emailAddress], EMAIL_ADDR_DB_KEY).yieldsAsync();
storageStub.storeList.withArgs([username], USERNAME_DB_KEY).yieldsAsync();
storageStub.storeList.withArgs([realname], REALNAME_DB_KEY).yieldsAsync();
storageStub.storeList.withArgs([imap], IMAP_DB_KEY).yieldsAsync();
storageStub.storeList.withArgs([smtp], SMTP_DB_KEY).yieldsAsync();
pgpStub.encrypt.withArgs(password).yields(null, encryptedPassword);
auth.storeCredentials(function(err) {
expect(err).to.not.exist;
storageStub.storeList.withArgs([encryptedPassword], PASSWD_DB_KEY).returns(resolves());
storageStub.storeList.withArgs([emailAddress], EMAIL_ADDR_DB_KEY).returns(resolves());
storageStub.storeList.withArgs([username], USERNAME_DB_KEY).returns(resolves());
storageStub.storeList.withArgs([realname], REALNAME_DB_KEY).returns(resolves());
storageStub.storeList.withArgs([imap], IMAP_DB_KEY).returns(resolves());
storageStub.storeList.withArgs([smtp], SMTP_DB_KEY).returns(resolves());
pgpStub.encrypt.withArgs(password).returns(resolves(encryptedPassword));
auth.storeCredentials().then(function() {
expect(storageStub.storeList.callCount).to.equal(6);
expect(pgpStub.encrypt.calledOnce).to.be.true;
@ -186,13 +181,11 @@ describe('Auth unit tests', function() {
oauthStub.refreshToken.withArgs({
emailAddress: emailAddress,
oldToken: 'oldToken'
}).yieldsAsync(null, oauthToken);
}).returns(resolves(oauthToken));
auth.getOAuthToken(function(err) {
expect(err).to.not.exist;
auth.getOAuthToken().then(function() {
expect(auth.emailAddress).to.equal(emailAddress);
expect(auth.oauthToken).to.equal(oauthToken);
expect(oauthStub.refreshToken.calledOnce).to.be.true;
done();
@ -201,13 +194,11 @@ describe('Auth unit tests', function() {
it('should fetch token with known email address', function(done) {
auth.emailAddress = emailAddress;
oauthStub.getOAuthToken.withArgs(emailAddress).yieldsAsync(null, oauthToken);
oauthStub.getOAuthToken.withArgs(emailAddress).returns(resolves(oauthToken));
auth.getOAuthToken(function(err) {
expect(err).to.not.exist;
auth.getOAuthToken().then(function() {
expect(auth.emailAddress).to.equal(emailAddress);
expect(auth.oauthToken).to.equal(oauthToken);
expect(oauthStub.getOAuthToken.calledOnce).to.be.true;
done();
@ -215,14 +206,12 @@ describe('Auth unit tests', function() {
});
it('should fetch token with unknown email address', function(done) {
oauthStub.getOAuthToken.withArgs(undefined).yieldsAsync(null, oauthToken);
oauthStub.queryEmailAddress.withArgs(oauthToken).yieldsAsync(null, emailAddress);
oauthStub.getOAuthToken.withArgs(undefined).returns(resolves(oauthToken));
oauthStub.queryEmailAddress.withArgs(oauthToken).returns(resolves(emailAddress));
auth.getOAuthToken(function(err) {
expect(err).to.not.exist;
auth.getOAuthToken().then(function() {
expect(auth.emailAddress).to.equal(emailAddress);
expect(auth.oauthToken).to.equal(oauthToken);
expect(oauthStub.getOAuthToken.calledOnce).to.be.true;
expect(oauthStub.queryEmailAddress.calledOnce).to.be.true;
@ -231,14 +220,13 @@ describe('Auth unit tests', function() {
});
it('should fail when email address fetch fails', function(done) {
oauthStub.getOAuthToken.yieldsAsync(null, oauthToken);
oauthStub.queryEmailAddress.yieldsAsync(new Error());
oauthStub.getOAuthToken.returns(resolves(oauthToken));
oauthStub.queryEmailAddress.returns(rejects(new Error()));
auth.getOAuthToken(function(err) {
auth.getOAuthToken().catch(function(err) {
expect(err).to.exist;
expect(auth.emailAddress).to.not.exist;
expect(auth.oauthToken).to.not.exist;
expect(oauthStub.getOAuthToken.calledOnce).to.be.true;
expect(oauthStub.queryEmailAddress.calledOnce).to.be.true;
@ -247,13 +235,12 @@ describe('Auth unit tests', function() {
});
it('should fail when oauth fetch fails', function(done) {
oauthStub.getOAuthToken.yieldsAsync(new Error());
oauthStub.getOAuthToken.returns(rejects(new Error()));
auth.getOAuthToken(function(err) {
auth.getOAuthToken().catch(function(err) {
expect(err).to.exist;
expect(auth.emailAddress).to.not.exist;
expect(auth.oauthToken).to.not.exist;
expect(oauthStub.getOAuthToken.calledOnce).to.be.true;
expect(oauthStub.queryEmailAddress.called).to.be.false;
@ -264,15 +251,14 @@ describe('Auth unit tests', function() {
describe('#_loadCredentials', function() {
it('should work', function(done) {
storageStub.listItems.withArgs(EMAIL_ADDR_DB_KEY, 0, null).yieldsAsync(null, [emailAddress]);
storageStub.listItems.withArgs(PASSWD_DB_KEY, 0, null).yieldsAsync(null, [encryptedPassword]);
storageStub.listItems.withArgs(USERNAME_DB_KEY, 0, null).yieldsAsync(null, [username]);
storageStub.listItems.withArgs(REALNAME_DB_KEY, 0, null).yieldsAsync(null, [realname]);
storageStub.listItems.withArgs(IMAP_DB_KEY, 0, null).yieldsAsync(null, [imap]);
storageStub.listItems.withArgs(SMTP_DB_KEY, 0, null).yieldsAsync(null, [smtp]);
storageStub.listItems.withArgs(EMAIL_ADDR_DB_KEY, 0, null).returns(resolves([emailAddress]));
storageStub.listItems.withArgs(PASSWD_DB_KEY, 0, null).returns(resolves([encryptedPassword]));
storageStub.listItems.withArgs(USERNAME_DB_KEY, 0, null).returns(resolves([username]));
storageStub.listItems.withArgs(REALNAME_DB_KEY, 0, null).returns(resolves([realname]));
storageStub.listItems.withArgs(IMAP_DB_KEY, 0, null).returns(resolves([imap]));
storageStub.listItems.withArgs(SMTP_DB_KEY, 0, null).returns(resolves([smtp]));
auth._loadCredentials(function(err) {
expect(err).to.not.exist;
auth._loadCredentials().then(function() {
expect(auth.emailAddress).to.equal(emailAddress);
expect(auth.password).to.equal(encryptedPassword);
expect(auth.imap).to.equal(imap);
@ -289,9 +275,9 @@ describe('Auth unit tests', function() {
});
it('should fail', function(done) {
storageStub.listItems.yieldsAsync(new Error());
storageStub.listItems.returns(rejects(new Error()));
auth._loadCredentials(function(err) {
auth._loadCredentials().catch(function(err) {
expect(err).to.exist;
expect(auth.emailAddress).to.not.exist;
expect(auth.password).to.not.exist;
@ -319,23 +305,22 @@ describe('Auth unit tests', function() {
it('should work for Trust on first use', function(done) {
auth.imap = {};
storeCredentialsStub.yields();
storeCredentialsStub.returns(resolves());
function callback(err) {
expect(err).to.not.exist;
function callback() {
expect(storeCredentialsStub.callCount).to.equal(1);
done();
}
auth.handleCertificateUpdate('imap', onConnectDummy, callback, dummyCert);
auth.handleCertificateUpdate('imap', onConnectDummy, callback, dummyCert).then(callback);
});
it('should work for stored cert', function() {
auth.imap = {
ca: dummyCert
};
storeCredentialsStub.yields();
storeCredentialsStub.returns(resolves());
auth.handleCertificateUpdate('imap', onConnectDummy, onConnectDummy, dummyCert);
auth.handleCertificateUpdate('imap', onConnectDummy, dummyCert);
expect(storeCredentialsStub.callCount).to.equal(0);
});
@ -344,7 +329,7 @@ describe('Auth unit tests', function() {
ca: 'other',
pinned: true
};
storeCredentialsStub.yields();
storeCredentialsStub.returns(resolves());
function callback(err) {
expect(err).to.exist;
@ -352,50 +337,45 @@ describe('Auth unit tests', function() {
expect(storeCredentialsStub.callCount).to.equal(0);
done();
}
auth.handleCertificateUpdate('imap', onConnectDummy, callback, dummyCert);
auth.handleCertificateUpdate('imap', onConnectDummy, dummyCert).catch(callback);
});
it('should work for updated cert', function(done) {
auth.imap = {
ca: 'other'
};
storeCredentialsStub.yields();
storeCredentialsStub.returns(resolves());
function callback(err) {
if (err && err.callback) {
expect(err).to.exist;
expect(err.message).to.exist;
expect(storeCredentialsStub.callCount).to.equal(0);
err.callback(true);
} else {
expect(storeCredentialsStub.callCount).to.equal(1);
done();
err.callback(true).then(function() {
expect(storeCredentialsStub.callCount).to.equal(1);
done();
});
}
}
function onConnect(callback) {
callback();
}
auth.handleCertificateUpdate('imap', onConnect, callback, dummyCert);
auth.handleCertificateUpdate('imap', onConnectDummy, dummyCert).catch(callback);
});
});
describe('#logout', function() {
it('should fail to to error in calling db clear', function(done) {
storageStub.clear.yields(new Error());
storageStub.clear.returns(rejects(new Error()));
auth.logout(function(err) {
auth.logout().catch(function(err) {
expect(err).to.exist;
done();
});
});
it('should work', function(done) {
storageStub.clear.yields();
storageStub.clear.returns(resolves());
auth.logout(function(err) {
expect(err).to.not.exist;
auth.logout().then(function() {
expect(auth.password).to.be.undefined;
expect(auth.initialized).to.be.undefined;
expect(auth.credentialsDirty).to.be.undefined;