From 26553e49d778a0334f4a3392801278926ae446a0 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Thu, 11 Dec 2014 20:27:55 +0100 Subject: [PATCH] Refactor auth --- src/js/email/account.js | 4 +- src/js/service/auth.js | 327 ++++++++++++++------------------- test/unit/service/auth-test.js | 136 ++++++-------- 3 files changed, 193 insertions(+), 274 deletions(-) diff --git a/src/js/email/account.js b/src/js/email/account.js index 8287821..b665d36 100644 --- a/src/js/email/account.js +++ b/src/js/email/account.js @@ -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({ diff --git a/src/js/service/auth.js b/src/js/service/auth.js index 6264b14..df7d445 100644 --- a/src/js/service/auth.js +++ b/src/js/service/auth.js @@ -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(); }); }; \ No newline at end of file diff --git a/test/unit/service/auth-test.js b/test/unit/service/auth-test.js index 5d48b80..17a81b1 100644 --- a/test/unit/service/auth-test.js +++ b/test/unit/service/auth-test.js @@ -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;